home *** CD-ROM | disk | FTP | other *** search
/ Total Network Tools 2002 / NextStepPublishing-TotalNetworkTools2002-Win95.iso / Archive / Offline Browsing / HTTrack.exe / data1.cab / Sources / src / httrack.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-04-28  |  129.7 KB  |  3,645 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: Main source                                            */
  34. /* Author: Xavier Roche                                         */
  35. /* ------------------------------------------------------------ */
  36.  
  37. #include "httrack.h"
  38.  
  39. /* specific definitions */
  40. #include "htsbase.h"
  41. #include "htsnet.h"
  42. #include "htsbauth.h"
  43. #include "htsmd5.h"
  44. #include "htsindex.h"
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <time.h>
  49. #include <fcntl.h>
  50. #include <ctype.h>
  51. /* END specific definitions */
  52.  
  53.  
  54. /* HTML parsing */
  55. #if HTS_ANALYSTE==2
  56. char _hts_errmsg[1100]="";
  57. int _hts_in_html_parsing=0;
  58. int _hts_in_html_done=0;  // % done
  59. int _hts_in_html_poll=0;  // parsing
  60. int _hts_setpause=0;
  61. httrackp* _hts_setopt=NULL;
  62. char** _hts_addurl=NULL;
  63. //
  64. int _hts_cancel=0;
  65. #endif
  66.  
  67.  
  68.  
  69. char* structcheck_buff=NULL;
  70. int exit_xh;          /* quick exit (fatal error or interrupt) */
  71.  
  72. /* debug */
  73. #if DEBUG_SHOWTYPES
  74. char REG[32768]="\n";
  75. #endif
  76. #if NSDEBUG
  77. int nsocDEBUG=0;
  78. #endif
  79.  
  80. //
  81. #define _CLRSCR printf("\33[m\33[2J");
  82. #define _GOTOXY(X,Y) printf("\33[" X ";" Y "f");
  83.  
  84. #if DEBUG_CHECKINT
  85.  #define _CHECKINT_FAIL(a) printf("\n%s\n",a); fflush(stdout); exit(1);
  86.  #define _CHECKINT(obj_ptr,message) \
  87.    if (obj_ptr) {\
  88.      if (( * ((char*) (obj_ptr)) != 0) || ( * ((char*) (((char*) (obj_ptr)) + sizeof(*(obj_ptr))-1)) != 0)) {\
  89.        char msg[1100];\
  90.        if (( * ((char*) (obj_ptr)) != 0) && ( * ((char*) (((char*) (obj_ptr)) + sizeof(*(obj_ptr))-1)) != 0))\
  91.          sprintf(msg,"* PANIC: Integrity error (structure crushed)  in: %s",message);\
  92.        else if ( * ((char*) (obj_ptr)) != 0)\
  93.          sprintf(msg,"* PANIC: Integrity error (start of structure) in: %s",message);\
  94.        else\
  95.          sprintf(msg,"* PANIC: Integrity error (end of structure)   in: %s",message);\
  96.        _CHECKINT_FAIL(msg);\
  97.      }\
  98.    } else {\
  99.      char msg[1100];\
  100.      sprintf(msg,"* PANIC: NULL pointer in: %s",message);\
  101.      _CHECKINT_FAIL(msg);\
  102.    }
  103. #endif
  104.  
  105. #if DEBUG_HASH
  106.   // longest hash chain?
  107.   int longest_hash[3]={0,0,0},hashnumber=0;
  108. #endif
  109.  
  110. // demande d'interaction avec le shell
  111. #if HTS_ANALYSTE==2
  112. char HTbuff[1100];
  113. #endif
  114.  
  115.  
  116.  
  117. // DΘbut de httpmirror, routines annexes
  118.  
  119. // version 1 pour httpmirror
  120. // flusher si on doit lire peu α peu le fichier
  121. #define test_flush if (opt.flush) { fflush(opt.log); fflush(opt.errlog); }
  122.  
  123. // pour allΘger la syntaxe, des raccourcis sont crΘΘs
  124. #define urladr   (liens[ptr]->adr)
  125. #define urlfil   (liens[ptr]->fil)
  126. #define savename (liens[ptr]->sav)
  127. //#define level    (liens[ptr]->depth)
  128. #define new_stat_bytes (HTS_STAT.HTS_TOTAL_RECV)
  129.  
  130. // au cas o∙ nous devons quitter rapidement xhttpmirror (plus de mΘmoire, etc)
  131. // note: partir de liens_max.. vers 0.. sinon erreur de violation de mΘmoire: les liens suivants
  132. // ne sont plus α nous.. agh! [dur celui-lα]
  133. #if HTS_ANALYSTE
  134.  #define HTMLCHECK_UNINIT hts_htmlcheck_end();
  135. #else
  136. #define HTMLCHECK_UNINIT 
  137. #endif
  138.  
  139. #define XH_extuninit { \
  140.   int i; \
  141.   HTMLCHECK_UNINIT \
  142.   if (liens!=NULL) { \
  143.   for(i=lien_max-1;i>0;i--) { \
  144.   if (liens[i]) { \
  145.   if (liens[i]->firstblock==1) { \
  146.   freet(liens[i]); \
  147.   liens[i]=NULL; \
  148.   } \
  149.   } \
  150.   } \
  151.   liens=NULL; \
  152.   } \
  153.   if (filters[0]) { \
  154.   freet(filters[0]); filters[0]=NULL; \
  155.   } \
  156.   if (back) { \
  157.   int i; \
  158.   for(i=0;i<back_max;i++) { \
  159.   back_delete(back,i); \
  160.   } \
  161.   freet(back); back=NULL;  \
  162.   } \
  163.   checkrobots_free(&robots);\
  164.   if (cache.use) { freet(cache.use); cache.use=NULL; } \
  165.   if (cache.dat) { fclose(cache.dat); cache.dat=NULL; }  \
  166.   if (cache.ndx) { fclose(cache.ndx); cache.ndx=NULL; } \
  167.   if (cache.olddat) { fclose(cache.olddat); cache.olddat=NULL; } \
  168.   if (cache.lst) { fclose(cache.lst); cache.lst=NULL; } \
  169.   if (opt.log) fflush(opt.log); \
  170.   if (opt.errlog) fflush(opt.errlog);\
  171.   if (makestat_fp) { fclose(makestat_fp); makestat_fp=NULL; } \
  172.   if (maketrack_fp){ fclose(maketrack_fp); maketrack_fp=NULL; } \
  173.   if (opt.accept_cookie) cookie_save(opt.cookie,fconcat(opt.path_log,"cookies.txt")); \
  174.   if (makeindex_fp) { fclose(makeindex_fp); makeindex_fp=NULL; } \
  175.   if (cache_hash) { inthash_del(cache_hash,cache_hash_size); cache_hash=NULL; } \
  176. }
  177. #define XH_uninit XH_extuninit if (r.adr) { freet(r.adr); r.adr=NULL; } 
  178.  
  179. // Enregistrement d'un lien:
  180. // on calcule la taille nΘcessaire: taille des 3 chaεnes α stocker (taille forcΘe paire, plus 2 octets de sΘcuritΘ)
  181. // puis on vΘrifie qu'on a assez de marge dans le buffer - sinon on en rΘalloue un autre
  182. // enfin on Θcrit α l'adresse courante du buffer, qu'on incrΘmente. on dΘcrΘmente la taille dispo d'autant ensuite
  183. // codebase: si non nul et si .class stockee on le note pour chemin primaire pour classes
  184. // FA,FS: former_adr et former_fil, lien original
  185. #define HTS_ALIGN 4
  186. #if HTS_HASH
  187. #define liens_record_sav_len(A) 
  188. #else
  189. #define liens_record_sav_len(A) (A)->sav_len=strlen((A)->sav)
  190. #endif
  191.  
  192. #define liens_record(A,F,S,FA,FF) { \
  193. int notecode=0; \
  194. int adr_len=strlen(A),fil_len=strlen(F),sav_len=strlen(S),cod_len=0,former_adr_len=strlen(FA),former_fil_len=strlen(FF); \
  195. if (former_adr_len>0) {\
  196. former_adr_len=(former_adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  197. former_fil_len=(former_fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  198. } else former_adr_len=former_fil_len=0;\
  199. if (strlen(F)>6) if (strnotempty(codebase)) if (strfield(F+strlen(F)-6,".class")) { notecode=1; \
  200. cod_len=strlen(codebase); cod_len=(cod_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; } \
  201. adr_len=(adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; fil_len=(fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; sav_len=(sav_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  202. if ((int) lien_size < (int) (adr_len+fil_len+sav_len+cod_len+former_adr_len+former_fil_len+sizeof(lien_url))) { \
  203. lien_buffer=(char*) ((void*) calloct(add_tab_alloc,1)); \
  204. lien_size=add_tab_alloc; \
  205. if (lien_buffer!=NULL) { \
  206. liens[lien_tot]=(lien_url*) (void*) lien_buffer; lien_buffer+=sizeof(lien_url); lien_size-=sizeof(lien_url); \
  207. liens[lien_tot]->firstblock=1; \
  208. } \
  209. } else { \
  210. liens[lien_tot]=(lien_url*) (void*) lien_buffer; lien_buffer+=sizeof(lien_url); lien_size-=sizeof(lien_url); \
  211. liens[lien_tot]->firstblock=0; \
  212. } \
  213. if (liens[lien_tot]!=NULL) { \
  214. liens[lien_tot]->adr=lien_buffer; lien_buffer+=adr_len; lien_size-=adr_len; \
  215. liens[lien_tot]->fil=lien_buffer; lien_buffer+=fil_len; lien_size-=fil_len; \
  216. liens[lien_tot]->sav=lien_buffer; lien_buffer+=sav_len; lien_size-=sav_len; \
  217. liens[lien_tot]->cod=NULL; \
  218. if (notecode) { liens[lien_tot]->cod=lien_buffer; lien_buffer+=cod_len; lien_size-=cod_len; strcpy(liens[lien_tot]->cod,codebase); } \
  219. if (former_adr_len>0) {\
  220. liens[lien_tot]->former_adr=lien_buffer; lien_buffer+=former_adr_len; lien_size-=former_adr_len; \
  221. liens[lien_tot]->former_fil=lien_buffer; lien_buffer+=former_fil_len; lien_size-=former_fil_len; \
  222. strcpy(liens[lien_tot]->former_adr,FA); \
  223. strcpy(liens[lien_tot]->former_fil,FF); \
  224. }\
  225. strcpy(liens[lien_tot]->adr,A); \
  226. strcpy(liens[lien_tot]->fil,F); \
  227. strcpy(liens[lien_tot]->sav,S); \
  228. liens_record_sav_len(liens[lien_tot]); \
  229. hash_write(&hash,lien_tot);  \
  230. } \
  231. }
  232.  
  233. /* - abandonnΘ (simplifie) -
  234. // Ajouter α un lien EXISTANT deux champs former_adr et former_fil pour indiquer le nom d'un fichier avant un "move"
  235. // NOTE: si un alloc est fait ici il n'y aura pas de freet() α la fin, tant pis (firstbloc)
  236. #define liens_add_former(index,A,F) { \
  237. int adr_len=strlen(A),fil_len=strlen(F); \
  238. adr_len=(adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; fil_len=(fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  239. if ((int) lien_size < (int) (adr_len+fil_len)) { \
  240. lien_buffer=(char*) calloct(add_tab_alloc,1); \
  241. lien_size=add_tab_alloc; \
  242. } \
  243. if (lien_buffer!=NULL) { \
  244. if (liens[lien_tot]!=NULL) { \
  245. liens[lien_tot]->former_adr=lien_buffer; lien_buffer+=adr_len; lien_size-=adr_len; \
  246. liens[lien_tot]->former_fil=lien_buffer; lien_buffer+=fil_len; lien_size-=fil_len; \
  247. strcpy(liens[lien_tot]->former_adr,A); \
  248. strcpy(liens[lien_tot]->former_fil,F); \
  249. } \
  250. } \
  251. }
  252. */
  253.  
  254. #if 0
  255. #define HT_ADD_ADR { \
  256.   fwrite(lastsaved,1,((int) adr)- ((int) lastsaved),fp); \
  257.   lastsaved=adr; }
  258. #define HT_ADD(A) fwrite(A,1,(int) strlen(A),fp);
  259. #define HT_ADD_START
  260. #define HT_ADD_END if (fp) { fclose(fp); fp=NULL; }
  261. #define HT_ADD_FOP { \
  262.   fp=filecreate(savename); \
  263.   if (fp==NULL) { \
  264.   if (opt.errlog) { \
  265.   fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unable to create %s for %s%s"LF,savename,urladr,urlfil); \
  266.   test_flush; \
  267.   } \
  268.   freet(r.adr); r.adr=NULL; \
  269.   error=1; \
  270.   } \
  271.   }
  272. #else
  273. // version optimisΘe, qui permet de ne pas toucher aux html non modifiΘs (update)
  274. #define HT_ADD_CHK(A) if (((int) A+ht_len+1)>ht_size) { \
  275.   ht_size=A+ht_len+8192; \
  276.   ht_buff=(char*) realloct(ht_buff,ht_size); \
  277.   if (ht_buff==NULL) { \
  278.   printf("PANIC! : Not enough memory [%d]\n",__LINE__); \
  279.   XH_uninit; \
  280.   } \
  281.   } \
  282.   ht_len+=A;
  283. #define HT_ADD_ADR { int i,j=ht_len; HT_ADD_CHK(((int) adr)- ((int) lastsaved)) \
  284.   for(i=0;i<((int) adr)- ((int) lastsaved);i++) \
  285.   ht_buff[j+i]=lastsaved[i]; \
  286.   ht_buff[j+((int) adr)- ((int) lastsaved)]='\0'; \
  287.   lastsaved=adr; }
  288. #define HT_ADD(A) { HT_ADD_CHK(strlen(A)) strcat(ht_buff,A); }
  289. #define HT_ADD_START \
  290.   int ht_size=(int)(r.size*5)/4+8192; \
  291.   int ht_len=0; \
  292.   char* ht_buff=NULL; \
  293.   if ((opt.getmode & 1) && (ptr>0)) { \
  294.   ht_buff=(char*) malloct(ht_size); \
  295.   if (ht_buff==NULL) { \
  296.   printf("PANIC! : Not enough memory [%d]\n",__LINE__); \
  297.   XH_uninit; \
  298.   } \
  299.   ht_buff[0]='\0'; \
  300.   }
  301. #define HT_ADD_END { \
  302.   int ok=0;\
  303.   if (ht_buff) { \
  304.   int file_len=(int) strlen(ht_buff);\
  305.   char digest[32+2];\
  306.   digest[0]='\0';\
  307.   domd5mem(ht_buff,file_len,digest,1,0);\
  308.   if (fsize(antislash(savename))==file_len) { \
  309.   int mlen;\
  310.   char* mbuff;\
  311.   cache_readdata(&cache,"//[HTML-MD5]//",savename,&mbuff,&mlen);\
  312.   if (mlen) mbuff[mlen]='\0';\
  313.   if ((mlen == 32) && (strcmp(((mbuff!=NULL)?mbuff:""),digest)==0)) {\
  314.   ok=1;\
  315.   if ( (opt.debug>1) && (opt.log!=NULL) ) {\
  316.   fspc(opt.log,"debug"); fprintf(opt.log,"File not re-written (md5): %s"LF,savename);\
  317.   test_flush;\
  318.   }\
  319.   } else {\
  320.   FILE* fp2; \
  321.   int i=0; \
  322.   fp2=fopen(fconv(savename),"rb"); \
  323.   if (fp2) { \
  324.   ok=1; \
  325.   while((!feof(fp2)) && (ok)) { int c=fgetc(fp2); if (c!=EOF) { if ((char) c!=(char) ht_buff[i++]) ok=0; } } \
  326.   fclose(fp2); \
  327.   } \
  328.   } \
  329.   }\
  330.   if (!ok) { \
  331.   fp=filecreate(savename); \
  332.   if (fp) { \
  333.   if ((int)fwrite(ht_buff,1,file_len,fp) != file_len) { \
  334.   if (opt.errlog) {   \
  335.   fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unable to write HTML file %s"LF,savename);\
  336.   test_flush;\
  337.   }\
  338.   }\
  339.   fclose(fp); fp=NULL; \
  340.   if (strnotempty(r.lastmodified)) \
  341.   set_filetime_rfc822(savename,r.lastmodified); \
  342.   usercommand(0,NULL,antislash(savename)); \
  343.   } \
  344.   } else filenote(savename,NULL); \
  345.   if (cache.ndx)\
  346.   cache_writedata(cache.ndx,cache.dat,"//[HTML-MD5]//",savename,digest,(int)strlen(digest));\
  347.   } \
  348.   freet(ht_buff); ht_buff=NULL; \
  349.   }
  350. #define HT_ADD_FOP 
  351. #endif
  352.  
  353. // libΘrer filters[0] pour insΘrer un ΘlΘment dans filters[0]
  354. #define HT_INSERT_FILTERS0 {\
  355.   int i;\
  356.   if (filptr>0) {\
  357.     for(i=filptr-1;i>=0;i--) {\
  358.       strcpy(filters[i+1],filters[i]);\
  359.     }\
  360.   }\
  361.   strcpy(filters[0],"");\
  362.   filptr++;\
  363.   filptr=minimum(filptr,filter_max);\
  364. }
  365.  
  366. // DΘbut de httpmirror, robot
  367. // url1 peut Ωtre multiple
  368. int httpmirror(char* url1,httrackp opt) {
  369.   char* primary=NULL;          // premiΦre page, contenant les liens α scanner
  370.   int lien_tot=0;              // nombre de liens pour le moment
  371.   lien_url** liens=NULL;       // les pointeurs sur les liens
  372.   hash_struct hash;            // systΦme de hachage, accΘlΦre la recherche dans les liens
  373.   t_cookie cookie;             // gestion des cookies
  374.   int lien_max=0;
  375.   int lien_size=0;        // octets restants dans buffer liens dispo
  376.   char* lien_buffer=NULL; // buffer liens actuel
  377.   int add_tab_alloc=256000;    // +256K de liens α chaque fois
  378.   //char* tab_alloc=NULL;
  379.   int ptr;             // pointeur actuel sur les liens
  380.   //
  381.   int numero_passe=0;  // deux passes pour html puis images
  382.   int back_max=0;      // fichiers qui peuvent Ωtre en local
  383.   lien_back* back=NULL; // backing en local
  384.   htsblk r;            // retour de certaines fonctions
  385.   double lastime=0;    // pour affichage infos de tmp en tmp
  386.   // pour les stats, nombre de fichiers & octets Θcrits
  387.   LLint stat_fragment=0;  // pour la fragmentation
  388.   //double istat_timestart;   // dΘpart pour calcul instantannΘ
  389.   //
  390.   double last_info_shell=0;
  391.   int info_shell=0;
  392.   // note: α amΘliorer // **
  393.   char* filters[usd_max];
  394.   int filter_max=0;
  395.   int filptr=0;
  396.   //
  397.   int makeindex_done=0;  // lorsque l'index sera fait
  398.   FILE* makeindex_fp=NULL;
  399.   int makeindex_links=0;
  400.   char makeindex_firstlink[HTS_URLMAXSIZE*2];
  401.   // statistiques (mode #Z)
  402.   FILE* makestat_fp=NULL;    // fichier de stats taux transfert
  403.   FILE* maketrack_fp=NULL;   // idem pour le tracking
  404.   double makestat_time=0;    // attente (secondes)
  405.   LLint makestat_total=0;    // repΦre du nombre d'octets transfΘrΘs depuis denriΦre stat
  406.   int makestat_lnk=0;        // idem, pour le nombre de liens
  407.   //
  408.   char codebase[HTS_URLMAXSIZE*2];  // base pour applet java
  409.   char base[HTS_URLMAXSIZE*2];      // base pour les autres fichiers
  410.   //
  411.   cache_back cache;
  412.   robots_wizard robots;    // gestion robots.txt
  413.   hash_chain** cache_hash=NULL;
  414.   int cache_hash_size=0;
  415.   //
  416.   codebase[0]='\0'; base[0]='\0';
  417.   //
  418.   cookie.auth.next=NULL;
  419.   cookie.auth.auth[0]=cookie.auth.prefix[0]='\0';
  420.   //
  421.  
  422.   // noter heure actuelle de dΘpart en secondes
  423.   bzero((char *)&HTS_STAT, sizeof(HTS_STAT));
  424.   HTS_STAT.stat_timestart=time_local();
  425.   //istat_timestart=stat_timestart;
  426.   HTS_STAT.imstat_timestart=mtime_local();
  427.   /* reset stats */
  428.   new_stat_bytes=0;
  429.   HTS_STAT.istat_bytes=0;
  430.   if (opt.aff_progress)
  431.     lastime=HTS_STAT.stat_timestart;
  432.   if (opt.shell) {
  433.     last_info_shell=HTS_STAT.stat_timestart;
  434.   }
  435.   if ((opt.makestat) || (opt.maketrack)){
  436.     makestat_time=HTS_STAT.stat_timestart;
  437.   }
  438.  
  439.   // initialiser cookie
  440.   if (opt.accept_cookie) {
  441.     opt.cookie=&cookie;
  442.     cookie.max_len=30000;       // max len
  443.     strcpy(cookie.data,"");
  444.     // Charger cookies.txt par dΘfaut ou cookies.txt du miroir
  445.     if (fexist(fconcat(opt.path_log,"cookies.txt")))
  446.       cookie_load(opt.cookie,opt.path_log,"cookies.txt");
  447.     else if (fexist("cookies.txt"))
  448.       cookie_load(opt.cookie,"","cookies.txt");
  449.   } else
  450.     opt.cookie=NULL;
  451.  
  452.   // initialiser exit_xh
  453.   exit_xh=0;          // sortir prΘmaturΘment (var globale)
  454.  
  455.   // initialiser usercommand
  456.   usercommand(opt.sys_com_exec,opt.sys_com,"");
  457.   
  458.   // Initialiser indexation
  459.   if (opt.kindex)
  460.     index_init(opt.path_html);
  461.  
  462.   // effacer bloc cache
  463.   bzero((char *)&cache, sizeof(cache_back));
  464.   cache.type=opt.cache;  // cache?
  465.   cache.errlog=opt.errlog;  // err log?
  466.   cache.ptr_ant=cache.ptr_last=0;   // pointeur pour anticiper
  467.  
  468.   // initialiser hash cache
  469.   if (!cache_hash_size) 
  470.     cache_hash_size=HTS_HASH_SIZE;
  471.   cache_hash=(hash_chain**)calloc(cache_hash_size,sizeof(hash_chain*));
  472.   if (cache_hash==NULL) {
  473.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  474.     filters[0]=NULL; back_max=0;    // uniquement a cause du warning de XH_extuninit
  475.     XH_extuninit;
  476.     return 0;
  477.   }
  478.   inthash_init(cache_hash,cache_hash_size);
  479.   cache.hash=(void**)cache_hash;      /* copy backcache hash */
  480.   cache.hash_size=cache_hash_size;
  481.  
  482.   // initialiser cache DNS
  483.   _hts_lockdns(-999);
  484.  
  485.   // robots.txt
  486.   strcpy(robots.adr,"!");    // dummy
  487.   robots.token[0]='\0';
  488.   robots.next=NULL;          // suivant
  489.   
  490.   // effacer filters
  491.   filter_max=maximum(opt.maxfilter,128);
  492.   filters[0]=(char*) malloct((filter_max+1)*(HTS_URLMAXSIZE*2));
  493.   if (filters[0]==NULL) {
  494.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  495.     back_max=0;    // uniquement a cause du warning de XH_extuninit
  496.     XH_extuninit;
  497.     return 0;
  498.   } else {
  499.     int i;
  500.     for(i=0;i<=filter_max;i++) {    // PLUS UN (sΘcuritΘ)
  501.       filters[i]=filters[0]+i*(HTS_URLMAXSIZE*2);
  502.       filters[i][0]='\0';
  503.     }
  504.   }
  505.   opt.filters.filptr=&filptr;
  506.   opt.filters.filter_max=&filter_max;
  507.   opt.filters.filters=filters;
  508.  
  509.   // tableau de pointeurs sur les liens
  510.   lien_max=maximum(opt.maxlink,32);
  511.   liens=(lien_url**) malloct(lien_max*sizeof(lien_url*));   // tableau de pointeurs sur les liens
  512.   if (liens==NULL) {
  513.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  514.     //XH_uninit;
  515.     return 0;
  516.   } else {
  517.     int i;
  518.     for(i=0;i<lien_max;i++) {
  519.       liens[i]=NULL;     
  520.     }
  521.   }
  522.   // initialiser ptr et lien_tot
  523.   ptr=0;
  524.   lien_tot=0;
  525. #if HTS_HASH
  526.   // initialiser hachage
  527.   {
  528.     int i;
  529.     for(i=0;i<HTS_HASH_SIZE;i++)
  530.       hash.hash[0][i]=hash.hash[1][i]=hash.hash[2][i] = -1;    // pas d'entrΘes
  531.     hash.liens = liens;
  532.     hash.max_lien=0;
  533.   }
  534. #endif
  535.  
  536.   
  537.   // copier adresse(s) dans liste des adresses
  538.   {
  539.     char *a=url1;
  540.     int primary_len=8192;
  541.     if (strnotempty(opt.filelist)) {
  542.       primary_len+=max(0,fsize(opt.filelist)*2);
  543.     }
  544.     primary_len+=strlen(url1)*2;
  545.  
  546.     // crΘation de la premiΦre page, qui contient les liens de base α scanner
  547.     // c'est plus propre et plus logique que d'entrer α la main les liens dans la pile
  548.     // on bΘnΘficie ainsi des vΘrifications et des tests du robot pour les liens "primaires"
  549.     primary=(char*) malloct(primary_len); 
  550.     if (primary) {
  551.       primary[0]='\0';
  552.     } else {
  553.       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  554.       back_max=0;    // uniquement a cause du warning de XH_extuninit
  555.       XH_extuninit;
  556.       return 0;
  557.     }
  558.     
  559.     while(*a) {
  560.       int i;
  561.       int joker=0;
  562.  
  563.       // vΘrifier qu'il n'y a pas de * dans l'url
  564.       if (*a=='+')
  565.         joker=1;
  566.       else if (*a=='-')
  567.         joker=1;
  568.       /* NON, certaines URL ont des * (!)
  569.       else {
  570.         int i=0;
  571.         while((a[i]!=0) && (a[i]!=' ')) if (a[i++]=='*') joker=1;
  572.       }
  573.       */
  574.       
  575.       if (joker) {    // joker ou filters
  576.         //char* p;
  577.         char tempo[HTS_URLMAXSIZE*2];
  578.         int type; int plus=0;
  579.  
  580.         // noter joker (dans b)
  581.         if (*a=='+') {  // champ +
  582.           type=1; plus=1; a++;
  583.         } else if (*a=='-') {  // champ forbidden[]
  584.           type=0; a++;
  585.         } else {  // champ + avec joker sans doute
  586.           type=1;
  587.         }
  588.  
  589.         // recopier prochaine chaine (+ ou -)
  590.         i=0;
  591.         while((*a!=0) && (*a!=' ')) { tempo[i++]=*a; a++; }  
  592.         tempo[i++]='\0';
  593.         while(*a==' ') { a++; }
  594.  
  595.         // sauter les + sans rien aprΦs..
  596.         if (strnotempty(tempo)) {
  597.           if ((plus==0) && (type==1)) {  // implicite: *www.edf.fr par exemple
  598.             if (tempo[strlen(tempo)-1]!='*') {
  599.               strcat(tempo,"*");  // ajouter un *
  600.             }
  601.           }
  602.           if (type)
  603.             strcpy(filters[filptr],"+");
  604.           else
  605.             strcpy(filters[filptr],"-");
  606.           if (strncmp(tempo,"http://",7)==0)
  607.             strcat(filters[filptr],tempo+7);        // ignorer http://
  608.           else if (strncmp(tempo,"ftp://",6)==0)
  609.             strcat(filters[filptr],tempo+6);        // ignorer ftp://
  610.           else
  611.             strcat(filters[filptr],tempo);
  612.           filptr++;          
  613.         }
  614.         
  615.       } else {    // adresse normale
  616.         char url[HTS_URLMAXSIZE*2];
  617.         // prochaine adresse
  618.         i=0;
  619.         while((*a!=0) && (*a!=' ')) { url[i++]=*a; a++; }  
  620.         while(*a==' ') { a++; }
  621.         url[i++]='\0';
  622.  
  623.         strcat(primary,"<PRIMARY=\"");
  624.         if (strstr(url,":/")==NULL)
  625.           strcat(primary,"http://");
  626.         strcat(primary,url);
  627.         strcat(primary,"\">\n");
  628.       }
  629.     }  // while
  630.  
  631.     /* intΘgrer liste de fichiers */
  632.     if (strnotempty(opt.filelist)) {
  633.       FILE* fp=fopen(opt.filelist,"rb");
  634.       if (fp) {
  635.         int n=0;
  636.         char line[512];
  637.         while(!feof(fp)) {
  638.           linput(fp,line,500);
  639.           if (strnotempty(line)) {
  640.             n++;
  641.             strcat(primary,"<PRIMARY=\"");
  642.             if (strstr(line,":/")==NULL)
  643.               strcat(primary,"http://");
  644.             strcat(primary,line);
  645.             strcat(primary,"\">\n");
  646.           }
  647.         }
  648.         fclose(fp);
  649.         if (opt.log!=NULL) {
  650.           fspc(opt.log,"info"); fprintf(opt.log,"%d links added from %s"LF,n,opt.filelist); test_flush;
  651.         }
  652.       } else {
  653.         if (opt.errlog!=NULL) {
  654.           fspc(opt.errlog,"error"); fprintf(opt.errlog,"Could not include URL list: %s"LF,opt.filelist); test_flush;
  655.         }
  656.       }
  657.     }
  658.  
  659.  
  660.     // lien primaire
  661.     liens_record("primary","/primary","primary.html","","");
  662.     if (liens[lien_tot]==NULL) {  // erreur, pas de place rΘservΘe
  663.       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  664.       if (opt.errlog) {
  665.         fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  666.         test_flush;
  667.       }
  668.       back_max=0;    // uniquement a cause du warning de XH_extuninit
  669.       XH_extuninit;    // dΘsallocation mΘmoire & buffers
  670.       return 0;
  671.     }    
  672.     liens[lien_tot]->testmode=0;          // pas mode test
  673.     liens[lien_tot]->link_import=0;       // pas mode import
  674.     liens[lien_tot]->depth=opt.depth+1;   // lien de prioritΘ maximale
  675.     liens[lien_tot]->pass2=0;             // 1Φre passe
  676.     liens[lien_tot]->retry=opt.retry;     // lien de prioritΘ maximale
  677.     liens[lien_tot]->premier=lien_tot;    // premier lien, objet-pΦre=objet              
  678.     liens[lien_tot]->precedent=lien_tot;  // lien prΘcΘdent
  679.     lien_tot++;  
  680.  
  681.     // Initialiser cache
  682.     cache_init(&cache,&opt);
  683.   }
  684.   
  685. #if BDEBUG==3
  686.   {
  687.     int i;
  688.     for(i=0;i<lien_tot;i++) {
  689.       printf("%d>%s%s as %s\n",i,liens[i]->adr,liens[i]->fil,liens[i]->sav);
  690.     }
  691.     for(i=0;i<filptr;i++) {
  692.       printf("%d>filters=%s\n",i,filters[i]);
  693.     }
  694.   }
  695. #endif
  696.    
  697.   // backing
  698.   //soc_max=opt.maxsoc;
  699.   if (opt.maxsoc>0) {
  700. #if BDEBUG==2
  701.     _CLRSCR;
  702. #endif
  703.     // Nombre de fichiers HTML pouvant Ωtre prΘsents en mΘmoire de maniΦre simultannΘe
  704.     // On prΘvoit large: les fichiers HTML ne prennent que peu de place en mΘmoire, et les
  705.     // fichiers non html sont sauvΘs en direct sur disque.
  706.     // --> 1024 entrΘes + 32 entrΘes par socket en supplΘment
  707.     back_max=opt.maxsoc*32+1024;
  708.     //back_max=opt.maxsoc*8+32;
  709.     back=(lien_back*) calloct((back_max+1),sizeof(lien_back));
  710.     if (back==NULL) {
  711.       if (opt.errlog)
  712.         fprintf(opt.errlog,"Not enough memory, can not allocate %d bytes"LF,(opt.maxsoc+1)*sizeof(lien_back));
  713.       return 0;
  714.     } else {    // copier buffer-location & effacer
  715.       int i;
  716.       for(i=0;i<back_max;i++){
  717.         back[i].r.location=back[i].location_buffer;
  718.         back[i].status=-1;
  719.         back[i].r.soc=INVALID_SOCKET;
  720.       }
  721.     }
  722.   }
  723.  
  724.  
  725.   // flush
  726.   test_flush;
  727.  
  728.   // statistiques
  729.   if (opt.makestat) {
  730.     makestat_fp=fopen(fconcat(opt.path_log,"hts-stats.txt"),"wb");
  731.     if (makestat_fp != NULL) {
  732.       fprintf(makestat_fp,"HTTrack statistics report, every minutes"LF LF);
  733.     }
  734.   }
  735.  
  736.   // tracking -- dΘbuggage
  737.   if (opt.maketrack) {
  738.     maketrack_fp=fopen(fconcat(opt.path_log,"hts-track.txt"),"wb");
  739.     if (maketrack_fp != NULL) {
  740.       fprintf(maketrack_fp,"HTTrack tracking report, every minutes"LF LF);
  741.     }
  742.   }
  743.  
  744.   // on n'a pas de liens!! (exemple: httrack www.* impossible sans dΘpart..)
  745.   if (lien_tot<=0) {
  746.     if (opt.errlog) {
  747.       fprintf(opt.errlog,"Error! You MUST specify at least one complete URL, and not only wildcards!"LF);
  748.     }
  749.   }
  750.  
  751.  
  752.   // attendre une certaine heure..
  753.   if (opt.waittime>0) {
  754.     int rollover=0;
  755.     int ok=0;
  756.     {
  757.       double tl=0;
  758.       time_t tt;
  759.       struct tm* A;
  760.       tt=time(NULL);
  761.       A=localtime(&tt);
  762.       tl+=A->tm_sec;
  763.       tl+=A->tm_min*60;
  764.       tl+=A->tm_hour*60*60;
  765.       if (tl>opt.waittime)  // attendre minuit
  766.         rollover=1;
  767.     }
  768.  
  769.     // attendre..
  770.     do {
  771.       double tl=0;
  772.       time_t tt;
  773.       struct tm* A;
  774.       tt=time(NULL);
  775.       A=localtime(&tt);
  776.       tl+=A->tm_sec;
  777.       tl+=A->tm_min*60;
  778.       tl+=A->tm_hour*60*60;
  779.  
  780.       if (rollover) {
  781.         if (tl<=opt.waittime)
  782.           rollover=0;  // attendre heure
  783.       } else {
  784.         if (tl>opt.waittime)
  785.           ok=1;  // ok!
  786.       }
  787.       
  788. #if HTS_ANALYSTE
  789.       {  
  790.         int r;
  791.         if (rollover)
  792.           r=hts_htmlcheck_loop(back,back_max,0,0,lien_tot,0,0,(int) (opt.waittime-tl+24*3600),-1,-1,-1,-1,-1,-1);
  793.         else
  794.           r=hts_htmlcheck_loop(back,back_max,0,0,lien_tot,0,0,(int) (opt.waittime-tl),-1,-1,-1,-1,-1,-1);
  795.         if (!r) {
  796.           exit_xh=1;  // exit requested
  797.           ok=1;          
  798.         } else
  799.           Sleep(100);
  800.       }
  801. #endif
  802.     } while(!ok);    
  803.     
  804.     // note: recopie de plus haut
  805.     // noter heure actuelle de dΘpart en secondes
  806.     HTS_STAT.stat_timestart=time_local();
  807.     if (opt.aff_progress)
  808.       lastime=HTS_STAT.stat_timestart;
  809.     if (opt.shell) {
  810.       last_info_shell=HTS_STAT.stat_timestart;
  811.     }
  812.     if ((opt.makestat) || (opt.maketrack)){
  813.       makestat_time=HTS_STAT.stat_timestart;
  814.     }
  815.  
  816.  
  817.   }  
  818. #if HTS_ANALYSTE
  819.   /*
  820.   if (!hts_htmlcheck_loop(back,back_max,0,0,lien_tot,0,0,0,-1,-1,-1,-1,-1)) {
  821.     XH_extuninit;
  822.     return 1;
  823.   }
  824.   Sleep(100);
  825.   */
  826.   if (!hts_htmlcheck_start()) {
  827.     XH_extuninit;
  828.     return 1;
  829.   }
  830. #endif
  831.   
  832.  
  833.   // ------------------------------------------------------------
  834.  
  835.   // ------------------------------------------------------------
  836.   // Boucle gΘnΘrale de parcours des liens
  837.   // ------------------------------------------------------------
  838.   do {
  839.     int error=0;          // si error alors sauter
  840.     int store_errpage=0;  // c'est une erreur mais on enregistre le html
  841.     char loc[HTS_URLMAXSIZE*2];    // adresse de relocation
  842.  
  843.     // Ici on charge le fichier (html, gif..) en mΘmoire
  844.     // Les HTMLs sont traitΘs (si leur prioritΘ est suffisante)
  845.  
  846.     // effacer r
  847.     bzero((char *)&r, sizeof(htsblk)); r.soc=INVALID_SOCKET;
  848.     r.location=loc;    // en cas d'erreur 3xx (moved)
  849.     // recopier proxy
  850.     bcopy((char*) &opt.proxy,(char*) &(r.req.proxy), sizeof(opt.proxy));
  851.     // et user-agent
  852.     strcpy(r.req.user_agent,opt.user_agent);
  853.     r.req.user_agent_send=opt.user_agent_send;
  854.  
  855.     if (!error) {
  856.       
  857.       // Skip empty/invalid/done in background
  858.       if (liens[ptr]) {
  859.         while (  (liens[ptr]) && (
  860.                     ( ((urladr != NULL)?(urladr):(" "))[0]=='!') ||
  861.                     ( ((urlfil != NULL)?(urlfil):(" "))[0]=='\0') ||
  862.                     ( (liens[ptr]->pass2 == -1) )
  863.                  )
  864.                ) {  // sauter si lien annulΘ (ou fil vide)
  865.           if ((opt.debug>1) && (opt.log!=NULL)) {
  866.             fspc(opt.log,"debug"); fprintf(opt.log,"link #%d seems ready, skipping: %s%s.."LF,ptr,((urladr != NULL)?(urladr):(" ")),((urlfil != NULL)?(urlfil):(" ")));
  867.             test_flush;
  868.           }
  869.           ptr++;
  870.         }
  871.       }
  872.       if (liens[ptr]) {    // on a qq chose α rΘcupΘrer?
  873.  
  874.         if ( (opt.debug>1) && (opt.log!=NULL) ) {
  875.           fspc(opt.log,"debug"); fprintf(opt.log,"Wait get: %s%s"LF,urladr,urlfil);
  876.           test_flush;
  877. #if DEBUG_ROBOTS
  878.           if (strcmp(urlfil,"/robots.txt") == 0) {
  879.             printf("robots.txt detected\n");
  880.           }
  881. #endif
  882.         }    
  883.         // ------------------------------------------------------------
  884.         // DEBUT --RECUPERATION LIEN---
  885.         if (ptr==0) {              // premier lien α parcourir: lien primaire construit avant
  886.           r.adr=primary; primary=NULL;
  887.           r.statuscode=200;
  888.           r.size=strlen(r.adr);
  889.           r.soc=INVALID_SOCKET;
  890.           strcpy(r.contenttype,"text/html");
  891.         /*} else if (opt.maxsoc<=0) {   // fichiers 1 α 1 en attente (pas de backing)
  892.           // charger le fichier en mΘmoire tout bΩtement
  893.           r=xhttpget(urladr,urlfil);
  894.           //
  895.         */
  896.         } else {    // backing, multiples sockets
  897.           //
  898.           int b;
  899.           int n;
  900.           
  901. #if BDEBUG==1
  902.           printf("\nBack test..\n");
  903. #endif
  904.  
  905.           if (opt.fragment>0) {
  906.             if ((HTS_STAT.stat_bytes-stat_fragment) > opt.fragment) {
  907.               while (back_nsoc(back,back_max)>0) {                  // attendre fin des transferts
  908.                 back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);
  909.                 Sleep(100);
  910.               }
  911.               // On dΘsalloue le buffer d'enregistrement des chemins crΘΘe, au cas o∙ pendant la pause
  912.               // l'utilisateur ferait un rm -r aprΦs avoir effectuΘ un tar
  913.               if (structcheck_buff) {
  914.                 freet(structcheck_buff);
  915.                 structcheck_buff=NULL;
  916.               }
  917.               {
  918.                 FILE* fp = fopen(fconcat(opt.path_log,"hts-paused.lock"),"wb");
  919.                 if (fp) {
  920.                   fspc(fp,"info");  // dater
  921.                   fprintf(fp,"Pause\nHTTrack is paused after retreiving "LLintP" bytes\nDelete this file to continue the mirror...\n\n",HTS_STAT.stat_bytes);
  922.                   fclose(fp);
  923.                 }
  924.               }
  925.               stat_fragment=HTS_STAT.stat_bytes;
  926.               while (fexist(fconcat(opt.path_log,"hts-paused.lock"))) {
  927.                 //back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);   inutile!! (plus de sockets actives)
  928.                 Sleep(1000);
  929.               }
  930.             }
  931.           }
  932.  
  933. #if HTS_ANALYSTE==2
  934.           // changement dans les prΘfΘrences
  935.           if (_hts_setopt) {
  936.             copy_htsopt(_hts_setopt,&opt);    // copier au besoin
  937.             _hts_setopt=NULL;                 // effacer callback
  938.           }
  939.           if (_hts_addurl) {
  940.             char add_adr[HTS_URLMAXSIZE*2];
  941.             char add_fil[HTS_URLMAXSIZE*2];
  942.             while(*_hts_addurl) {
  943.               char add_url[HTS_URLMAXSIZE*2];
  944.               add_adr[0]=add_fil[0]=add_url[0]='\0';
  945.               if (strstr(*_hts_addurl,"://")==NULL)
  946.                 strcpy(add_url,"http://");          // ajouter http://
  947.               strcat(add_url,*_hts_addurl);
  948.               if (ident_url(add_url,add_adr,add_fil)>=0) {
  949.                 // ----Ajout----
  950.                 // noter NOUVEAU lien
  951.                 char add_sav[HTS_URLMAXSIZE*2];
  952.                 // calculer lien et Θventuellement modifier addresse/fichier
  953.                 if (url_savename(add_adr,add_fil,add_sav,NULL,NULL,NULL,NULL,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe)!=-1) { 
  954.                   if (hash_read(&hash,add_sav,"",0)<0) {      // n'existe pas dΘja
  955.                     // enregistrer lien (MACRO)
  956.                     liens_record(add_adr,add_fil,add_sav,"","");
  957.                     if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  958.                       liens[lien_tot]->testmode=0;          // mode test?
  959.                       liens[lien_tot]->link_import=0;       // mode normal
  960.                       liens[lien_tot]->depth=opt.depth;
  961.                       liens[lien_tot]->pass2=max(0,numero_passe);
  962.                       liens[lien_tot]->retry=opt.retry;
  963.                       liens[lien_tot]->premier=lien_tot;
  964.                       liens[lien_tot]->precedent=lien_tot;
  965.                       lien_tot++;
  966.                       //
  967.                       if ((opt.debug>0) && (opt.log!=NULL)) {
  968.                         fspc(opt.log,"info"); fprintf(opt.log,"Link added by user: %s%s"LF,add_adr,add_fil); test_flush;
  969.                       }
  970.                       //
  971.                     } else {  // oups erreur, plus de mΘmoire!!
  972.                       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  973.                       if (opt.errlog) {
  974.                         fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  975.                         test_flush;
  976.                       }
  977.                       //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  978.                       XH_uninit;    // dΘsallocation mΘmoire & buffers
  979.                       return 0;
  980.                     }
  981.                   } else {
  982.                     if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  983.                       fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Existing link %s not added after user request"LF,add_adr,add_fil);
  984.                       test_flush;
  985.                     }
  986.                   }
  987.                   
  988.                 }
  989.               } else {
  990.                 if (opt.errlog) {
  991.                   fspc(opt.errlog,"error");
  992.                   fprintf(opt.errlog,"Error during URL decoding for %s%s"LF,add_url);
  993.                   test_flush;
  994.                 }
  995.               }
  996.               // ----Fin Ajout----
  997.               _hts_addurl++;                  // suivante
  998.             }
  999.             _hts_addurl=NULL;           // libΘrer _hts_addurl
  1000.           }
  1001.           // si une pause a ΘtΘ demandΘe
  1002.           if (_hts_setpause) {
  1003.             // index du lien actuel
  1004.             int b=back_index(back,back_max,urladr,urlfil,savename);
  1005.             if (b<0) b=0;    // forcer pour les stats
  1006.             while(_hts_setpause) {    // on fait la pause..
  1007.               LLint nb;
  1008.               int nbk;
  1009.               back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);
  1010.               nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  1011.               nbk=backlinks_done(liens,lien_tot,ptr);
  1012.               engine_stats();
  1013.               if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,nb,new_stat_bytes,(int) (time_local()-HTS_STAT.stat_timestart),back_nsoc(back,back_max),HTS_STAT.stat_files,HTS_STAT.stat_updated_files,fspc(NULL,"error"),(int)HTS_STAT.rate,nbk )) {
  1014.                 if (opt.errlog) {
  1015.                   fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  1016.                   test_flush;
  1017.                 }
  1018.                 exit_xh=1;  // exit requested
  1019.                 XH_uninit;
  1020.                 return 0;
  1021.               }
  1022.               if (back_nsoc(back,back_max)==0)
  1023.                 Sleep(250);  // tite pause
  1024.             }
  1025.           }
  1026. #endif
  1027.           
  1028.           // si le fichier n'est pas en backing, le mettre..
  1029.           if (!back_exist(back,back_max,urladr,urlfil,savename)) {
  1030. #if BDEBUG==1
  1031.             printf("crash backing: %s%s\n",liens[ptr]->adr,liens[ptr]->fil);
  1032. #endif
  1033.             if (back_add(back,back_max,&opt,&cache,urladr,urlfil,savename,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil,liens[ptr]->testmode,&liens[ptr]->pass2)==-1) {
  1034.               printf("PANIC! : Crash adding error, unexpected error found.. [%d]\n",__LINE__);
  1035. #if BDEBUG==1
  1036.               printf("error while crash adding\n");
  1037. #endif
  1038.               if (opt.errlog) {
  1039.                 fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unexpected backing error for %s%s"LF,urladr,urlfil);
  1040.                 test_flush;
  1041.               } 
  1042.               
  1043.             }
  1044.           }
  1045.           
  1046. #if BDEBUG==1
  1047.           printf("test number of socks\n");
  1048. #endif
  1049.           
  1050.           // ajouter autant de socket qu'on peut ajouter
  1051.           n=opt.maxsoc-back_nsoc(back,back_max);
  1052. #if BDEBUG==1
  1053.           printf("%d sockets available for backing\n",n);
  1054. #endif
  1055.  
  1056. #if HTS_ANALYSTE==2
  1057.           if ((n>0) && (!_hts_setpause)) {   // si sockets libre et pas en pause, ajouter
  1058. #else
  1059.           if (n>0) {                         // si sockets libre
  1060. #endif
  1061.             // remplir autant que l'on peut le cache (backing)
  1062.             back_fillmax(back,back_max,&opt,&cache,liens,ptr,numero_passe,lien_tot);
  1063.           }
  1064.           
  1065.           // index du lien actuel
  1066. /*
  1067.           b=back_index(back,back_max,urladr,urlfil,savename);
  1068.           
  1069.           if (b>=0) 
  1070. */
  1071.           {
  1072.             // ------------------------------------------------------------
  1073.             // attendre que le fichier actuel soit prΩt - BOUCLE D'ATTENTE
  1074.             do {
  1075.  
  1076.               // index du lien actuel
  1077.               b=back_index(back,back_max,urladr,urlfil,savename);
  1078. #if BDEBUG==1
  1079.               printf("back index %d, waiting\n",b);
  1080. #endif
  1081.               // Continue to the loop if link still present
  1082.               if (b<0)
  1083.                 continue;
  1084.               
  1085.               // Receive data
  1086.               if (back[b].status>0)
  1087.                 back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);
  1088.               
  1089.               // Continue to the loop if link still present
  1090.               b=back_index(back,back_max,urladr,urlfil,savename);
  1091.               if (b<0)
  1092.                 continue;
  1093.               
  1094.               // And fill the backing stack
  1095.               if (back[b].status>0)
  1096.                 back_fillmax(back,back_max,&opt,&cache,liens,ptr,numero_passe,lien_tot);
  1097.               
  1098.               // Continue to the loop if link still present
  1099.               b=back_index(back,back_max,urladr,urlfil,savename);
  1100.               if (b<0)
  1101.                 continue;
  1102.  
  1103.               // autres occupations de HTTrack: statistiques, boucle d'attente, etc.
  1104.               if ((opt.makestat) || (opt.maketrack)) {
  1105.                 double l=time_local();
  1106.                 if ((int) (l-makestat_time) >= 60) {   
  1107.                   if (makestat_fp != NULL) {
  1108.                     fspc(makestat_fp,"info");
  1109.                     fprintf(makestat_fp,"Rate= %d (/"LLintP") \11NewLinks= %d (/%d)"LF,(int) ((new_stat_bytes-makestat_total)/(l-makestat_time)), new_stat_bytes,(int) lien_tot-makestat_lnk,(int) lien_tot);
  1110.                     fflush(makestat_fp);
  1111.                     makestat_total=new_stat_bytes;
  1112.                     makestat_lnk=lien_tot;
  1113.                   }
  1114.                   if (maketrack_fp!=NULL) {
  1115.                     int i;
  1116.                     fspc(maketrack_fp,"info"); fprintf(maketrack_fp,LF);
  1117.                     for(i=0;i<back_max;i++) {
  1118.                       back_info(back,i,3,maketrack_fp);
  1119.                     }
  1120.                     fprintf(maketrack_fp,LF);
  1121.                     
  1122.                   }
  1123.                   makestat_time=l;
  1124.                 }
  1125.               }
  1126. #if HTS_ANALYSTE==2
  1127.               {
  1128.                 LLint nb;
  1129.                 int nbk;
  1130.                 int i;
  1131.                 {
  1132.                   char* s=hts_cancel_file("");
  1133.                   if (strnotempty(s)) {    // fichier α canceller
  1134.                     for(i=0;i<back_max;i++) {
  1135.                       if ((back[i].status>0)) {
  1136.                         if (strcmp(back[i].url_sav,s)==0) {  // ok trouvΘ
  1137.                           if (back[i].status != 1000) {
  1138. #if HTS_DEBUG_CLOSESOCK
  1139.                             DEBUG_W("user cancel: deletehttp\n");
  1140. #endif
  1141.                             if (back[i].r.soc!=INVALID_SOCKET) deletehttp(&back[i].r);
  1142.                             back[i].r.soc=INVALID_SOCKET;
  1143.                             back[i].r.statuscode=-1;
  1144.                             strcpy(back[i].r.msg,"Cancelled by User");
  1145.                             back[i].status=0;  // terminΘ
  1146.                           } else    // cancel ftp.. flag α 1
  1147.                             back[i].stop_ftp = 1;
  1148.                         }
  1149.                       }
  1150.                     }
  1151.                     s[0]='\0';
  1152.                   }
  1153.                 }
  1154.                 
  1155.                 engine_stats();
  1156.                 nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  1157.                 nbk=backlinks_done(liens,lien_tot,ptr);
  1158.                 if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,nb,new_stat_bytes,(int) (time_local()-HTS_STAT.stat_timestart),back_nsoc(back,back_max),HTS_STAT.stat_files,HTS_STAT.stat_updated_files,fspc(NULL,"error"),(int)HTS_STAT.rate,nbk )) {
  1159.                   if (opt.errlog) {
  1160.                     fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  1161.                     test_flush;
  1162.                   } 
  1163.                   exit_xh=1;  // exit requested
  1164.                   XH_uninit;
  1165.                   return 0;
  1166.                 }
  1167.               }
  1168.               
  1169. #endif
  1170. #if HTS_POLL      
  1171.               if ((opt.shell) || (opt.keyboard)) {
  1172.                 int rcvd=0;
  1173.                 double tl;
  1174.                 info_shell=1;
  1175.                 // Traitement Θventuel des requΦtes stdin etc.
  1176.                 while (check_stdin()) {  // donnΘes disponibles
  1177.                   char com[256];
  1178.                   com[0]='\0';
  1179.                   
  1180.                   if (!rcvd) rcvd=1;
  1181.                   linput(stdin,com,256);
  1182.  
  1183.                   if (strnotempty(com)) {
  1184.                     if (strlen(com)<=2) {
  1185.                       switch(*com) {
  1186.                       case '?': {    // Status?
  1187.                         if (back[b].status>0) printf("WAIT\n"); 
  1188.                         else printf("READY\n");
  1189.                                 }
  1190.                         break;
  1191.                       case 'f': {    // Fichier en attente?
  1192.                         if (back[b].status>0) printf("WAIT %s\n",back[b].url_fil); 
  1193.                         else printf("READY %s\n",back[b].url_fil);
  1194.                                 }
  1195.                         break;
  1196.                       case 'A': case 'F': {    // filters
  1197.                         int i;
  1198.                         for(i=0;i<filptr;i++) {
  1199.                           printf("%s ",filters[i]);
  1200.                         }
  1201.                         printf("\n");
  1202.                                 }
  1203.                         break;
  1204.                       case '#': {    // Afficher statistique sur le nombre de liens, etc
  1205.                         switch(*(com+1)) {
  1206.                         case 'l': printf("%d\n",lien_tot); break;  // nombre de liens enregistrΘs
  1207.                         case 's': printf("%d\n",back_nsoc(back,back_max)); break;  // nombre de sockets
  1208.                         case 'r': printf("%d\n",(int) (new_stat_bytes/(time_local()-HTS_STAT.stat_timestart))); break;  // taux de transfert
  1209.                         }
  1210.                                 }
  1211.                         break;
  1212.                       case 'K': if (*(com+1)=='!') {  // Kill
  1213.                         XH_uninit;
  1214.                         return -1;
  1215.                                 }
  1216.                         break;
  1217.                       case 'X': if (*(com+1)=='!') {  // exit
  1218.                         exit_xh=1;
  1219.                                 }
  1220.                         break;
  1221.                       case 'I': if (*(com+1)=='+') info_shell=1; else info_shell=0;
  1222.                         break;
  1223.                       }
  1224.                       io_flush;
  1225.                     } else if (*com=='@') {
  1226.                       printf("%s\n",com+1);
  1227.                       io_flush;
  1228.                     }
  1229.                   } 
  1230.                   
  1231.                 }  // while
  1232.                 tl=time_local();
  1233.                 
  1234.                 // gΘnΘrer un message d'infos sur l'Θtat actuel
  1235.                 if (opt.shell) {    // si shell
  1236.                   if ((tl-last_info_shell)>0) {    // toute les 1 sec
  1237.                     FILE* fp=stdout;
  1238.                     int a=0;
  1239.                     last_info_shell=tl;
  1240.                     if (fexist(fconcat(opt.path_log,"hts-autopsy"))) {  // dΘbuggage: teste si le robot est vivant
  1241.                       // (oui je sais un robot vivant.. mais bon.. il a le droit de vivre lui aussi)
  1242.                       // (libΘrons les robots esclaves de l'internet!)
  1243.                       remove(fconcat(opt.path_log,"hts-autopsy"));
  1244.                       fp=fopen(fconcat(opt.path_log,"hts-isalive"),"wb");
  1245.                       a=1;
  1246.                     }
  1247.                     if ((info_shell) || a) {
  1248.                       int i,j;
  1249.                       
  1250.                       fprintf(fp,"TIME %d"LF,(int) (tl-HTS_STAT.stat_timestart));
  1251.                       fprintf(fp,"TOTAL %d"LF,(int) HTS_STAT.stat_bytes);
  1252.                       fprintf(fp,"RATE %d"LF,(int) (new_stat_bytes/(tl-HTS_STAT.stat_timestart)));
  1253.                       fprintf(fp,"SOCKET %d"LF,back_nsoc(back,back_max));
  1254.                       fprintf(fp,"LINK %d"LF,lien_tot);
  1255.                       {
  1256.                         LLint mem=0;
  1257.                         for(i=0;i<back_max;i++)
  1258.                           if (back[i].r.adr!=NULL)
  1259.                             mem+=back[i].r.size;
  1260.                           fprintf(fp,"INMEM "LLintP""LF,mem);
  1261.                       }
  1262.                       for(j=0;j<2;j++) {  // passes pour ready et wait
  1263.                         for(i=0;i<back_max;i++) {
  1264.                           back_info(back,i,j+1,stdout);    // maketrack_fp a la place de stdout ?? // **
  1265.                         }
  1266.                       }
  1267.                       fprintf(fp,LF);
  1268.                       if (a)
  1269.                         fclose(fp);
  1270.                       io_flush;
  1271.                     }
  1272.                   }
  1273.                 }  // si shell
  1274.                 
  1275.               }  // si shell ou keyboard (option)
  1276.               //
  1277. #endif
  1278.             } while((b>=0) && (back[max(b,0)].status>0));
  1279.  
  1280.  
  1281.             // If link not found on the stack, it's because it has already been downloaded
  1282.             // in background
  1283.             // Then, skip it and go to the next one
  1284.             if (b<0) {
  1285.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1286.                 fspc(opt.log,"debug"); fprintf(opt.log,"link #%d is ready, no more on the stack, skipping: %s%s.."LF,ptr,urladr,urlfil);
  1287.                 test_flush;
  1288.               }
  1289.  
  1290.               // prochain lien
  1291.               ptr++;
  1292.  
  1293.               // Jump to 'continue'
  1294.               // This is one of the very very rare cases where goto
  1295.               // is acceptable
  1296.               // A supplemental flag and if() { } would be really messy
  1297.               goto jump_if_done;
  1298.             }
  1299.             
  1300.  
  1301. #if HTS_ANALYSTE
  1302. #else
  1303.             if (!opt.quiet) {  // petite animation
  1304.               if (!opt.verbosedisplay) {
  1305.                 static int roll=0;
  1306.                 roll=(roll+1)%4;
  1307.                 printf("%c\x0d",("/-\\|")[roll]);
  1308.                 fflush(stdout);
  1309.               } else {
  1310.                 if (back[b].r.statuscode==200)
  1311.                   printf("%d/%d: %s%s ("LLintP" bytes) - OK\33[K\r",ptr,lien_tot,back[b].url_adr,back[b].url_fil,back[b].r.size);
  1312.                 else
  1313.                   printf("%d/%d: %s%s ("LLintP" bytes) - %d\33[K\r",ptr,lien_tot,back[b].url_adr,back[b].url_fil,back[b].r.size,back[b].r.statuscode);
  1314.                 fflush(stdout);
  1315.               }
  1316.             }
  1317. #endif
  1318.             // ------------------------------------------------------------
  1319.             // VΘrificateur d'intΘgritΘ
  1320. #if DEBUG_CHECKINT
  1321.             _CHECKINT(&back[b],"Retour de back_wait, aprΦs le while")
  1322.             {
  1323.               int i;
  1324.               for(i=0;i<back_max;i++) {
  1325.                 char si[256];
  1326.                 sprintf(si,"Test global aprΦs back_wait, index %d",i);
  1327.                 _CHECKINT(&back[i],si)
  1328.               }
  1329.             }
  1330. #endif
  1331.             
  1332.             // copier structure rΘponse htsblk
  1333.             bcopy((char*) &(back[b].r), (char*) &r, sizeof(htsblk));
  1334.             r.location=loc;    // ne PAS copier location!! adresse, pas de buffer
  1335.             if (back[b].r.location) 
  1336.               strcpy(r.location,back[b].r.location);
  1337.             back[b].r.adr=NULL;    // ne pas faire de desalloc ensuite
  1338.  
  1339.             // libΘrer emplacement backing
  1340.             back_delete(back,b);
  1341.             
  1342.             // progression
  1343.             if (opt.aff_progress) {
  1344.               double tl=time_local();
  1345.               if ((tl-lastime)>0) {
  1346.                 char s[32];
  1347.                 int i=0;
  1348.                 lastime=tl;
  1349.                 _CLRSCR; _GOTOXY("1","1");
  1350.                 printf("Rate=%d B/sec\n",(int) (new_stat_bytes/(tl-HTS_STAT.stat_timestart)));
  1351.                 while(i<minimum(back_max,99)) {  // **
  1352.                   if (back[i].status>=0) {  // loading..
  1353.                     s[0]='\0';
  1354.                     if (strlen(back[i].url_fil)>16)
  1355.                       strcat(s,back[i].url_fil+strlen(back[i].url_fil)-16);       
  1356.                     else
  1357.                       strncat(s,back[i].url_fil,16);
  1358.                     printf("%s : ",s);
  1359.                     
  1360.                     printf("[");
  1361.                     if (back[i].r.totalsize>0) {
  1362.                       int p;
  1363.                       int j;
  1364.                       p=(int)((back[i].r.size*10)/back[i].r.totalsize);
  1365.                       p=minimum(10,p);
  1366.                       for(j=0;j<p;j++) printf("*");
  1367.                       for(j=0;j<(10-p);j++) printf("-");
  1368.                     } else { 
  1369.                       printf(LLintP,back[i].r.size);                      
  1370.                     }
  1371.                     printf("]");
  1372.                     
  1373.                     //} else if (back[i].status==0) {
  1374.                     //  strcpy(s,"ENDED");
  1375.                   } 
  1376.                   printf("\n");
  1377.                   i++;
  1378.                 }
  1379.                 io_flush;
  1380.               }
  1381.             }
  1382.             
  1383.             // dΘbug graphique
  1384. #if BDEBUG==2
  1385.             {
  1386.               char s[12];
  1387.               int i=0;
  1388.               _GOTOXY(1,1);
  1389.               printf("Rate=%d B/sec\n",(int) (new_stat_bytes/(time_local()-HTS_STAT.stat_timestart)));
  1390.               while(i<minimum(back_max,160)) {
  1391.                 if (back[i].status>0) {
  1392.                   sprintf(s,"%d",back[i].r.size);
  1393.                 } else if (back[i].status==0) {
  1394.                   strcpy(s,"ENDED");
  1395.                 } else 
  1396.                   strcpy(s,"   -   ");
  1397.                 while(strlen(s)<8) strcat(s," ");
  1398.                 printf("%s",s); io_flush;
  1399.                 i++;
  1400.               }
  1401.             }
  1402. #endif
  1403.             
  1404.             
  1405. #if BDEBUG==1
  1406.             printf("statuscode=%d with %s / msg=%s\n",r.statuscode,r.contenttype,r.msg);
  1407. #endif
  1408.             
  1409.           }
  1410.           /*else {
  1411. #if BDEBUG==1
  1412.             printf("back index error\n");
  1413. #endif
  1414.           }
  1415.           */
  1416.           
  1417.         }
  1418.         // FIN --RECUPERATION LIEN--- 
  1419.         // ------------------------------------------------------------
  1420.  
  1421.  
  1422.  
  1423.       } else {    // lien vide..
  1424.         if (opt.errlog) {
  1425.           fprintf(opt.errlog,"Error Link empty"LF); test_flush;
  1426.           error=1;
  1427.         }         
  1428.       }  // test si url existe (non vide!)
  1429.       
  1430.  
  1431.  
  1432.       // ---tester taille a posteriori---
  1433.       // tester r.adr
  1434.       if (!error) {
  1435.         // erreur, pas de fichier chargΘ:
  1436.         if ((!r.adr) && (r.is_write==0) 
  1437.           && (r.statuscode!=301) 
  1438.           && (r.statuscode!=302) 
  1439.           && (r.statuscode!=303) 
  1440.           && (r.statuscode!=307) 
  1441.           && (r.statuscode!=412)
  1442.           && (r.statuscode!=416)
  1443.          ) { 
  1444.           error=1;
  1445.           
  1446.           // peut Ωtre que le fichier Θtait trop gros?
  1447.           if ((istoobig(r.totalsize,opt.maxfile_html,opt.maxfile_nonhtml,r.contenttype))
  1448.            || (istoobig(r.totalsize,opt.maxfile_html,opt.maxfile_nonhtml,r.contenttype))) {
  1449.             error=0;
  1450.             if (opt.errlog) {
  1451.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Big file cancelled according to user's preferences: %s%s"LF,urladr,urlfil);
  1452.               test_flush;
  1453.             }
  1454.           }
  1455.           error=1;    // ne pas traiter la suite -- euhh si finalement..
  1456.         }
  1457.       }
  1458.       // ---fin tester taille a posteriori---    
  1459.  
  1460.  
  1461.       // -------------------- 
  1462.       // REAL MEDIA HACK
  1463.       // Check if we have to load locally the file
  1464.       // --------------------
  1465.       if (!error) {
  1466.         if (r.adr==NULL) {    // Written file
  1467.           if (may_be_hypertext_mime(r.contenttype)) {   // to parse!
  1468.             LLint sz;
  1469.             sz=fsize(savename);
  1470.             if (sz>0) {   // ok, exists!
  1471.               if (sz < 512) {   // ok, small file --> to parse!
  1472.                 FILE* fp=fopen(savename,"rb");
  1473.                 if (fp) {
  1474.                   r.adr=malloc((int)sz + 2);
  1475.                   if (r.adr) {
  1476.                     fread(r.adr,(int)sz,1,fp);
  1477.                     r.size=sz;
  1478.                     // remove (temporary) file!
  1479.                     remove(savename);
  1480.                   }
  1481.                   fclose(fp);
  1482.                 }
  1483.               }
  1484.             }
  1485.           }
  1486.         }
  1487.       }
  1488.       // EN OF REAL MEDIA HACK
  1489.       
  1490.  
  1491.       // ---stockage en cache---
  1492.       // stocker dans le cache?
  1493.       if (!error) {
  1494.         if (ptr>0) {
  1495.           if (liens[ptr]) {
  1496.             cache_mayadd(&opt,&cache,&r,urladr,urlfil,savename);
  1497. #if 0        
  1498.             if (opt.cache) {
  1499.               if (cache.dat!=NULL) {
  1500.                 // c'est le seul endroit ou l'on ajoute des elements dans le cache (fichier entier ou header)
  1501.                 // on stocke tout fichier "ok", mais Θgalement les rΘponses 404,301,302...
  1502.                 if ((r.statuscode==200)         /* stocker rΘponse standard, plus */
  1503.                   || (r.statuscode==204)     /* no content */
  1504.                   || (r.statuscode==301)     /* moved perm */
  1505.                   || (r.statuscode==302)     /* moved temp */
  1506.                   || (r.statuscode==303)     /* moved temp */
  1507.                   || (r.statuscode==307)     /* moved temp */
  1508.                   || (r.statuscode==401)     /* authorization */
  1509.                   || (r.statuscode==403)     /* unauthorized */
  1510.                   || (r.statuscode==404)     /* not found */
  1511.                   || (r.statuscode==410)     /* gone */
  1512.                   )
  1513.                 {        /* ne pas stocker si la page gΘnΘrΘe est une erreur */
  1514.                   if (!r.is_file) {
  1515.                     // stocker fichiers (et robots.txt)
  1516.                     if ( (strnotempty(savename)) || (strcmp(urlfil,"/robots.txt")==0)) {
  1517.                       // ajouter le fichier au cache
  1518.                       cache_add(r,urladr,urlfil,savename,cache.ndx,cache.dat,opt.all_in_cache);
  1519.                     }
  1520.                   }
  1521.                 }
  1522.               }
  1523.             }
  1524. #endif
  1525.           } else
  1526.             error=1;
  1527.         }
  1528.       }
  1529.       // ---fin stockage en cache---
  1530.       
  1531.  
  1532.  
  1533.       // DEBUT rattrapage des 301,302,307..
  1534.       // ------------------------------------------------------------
  1535.       if (!error) {
  1536.       ////////{
  1537.         // on a chargΘ un fichier en plus
  1538.         // if (!error) stat_loaded+=r.size;
  1539.         
  1540.         // ------------------------------------------------------------
  1541.         // Rattrapage des 301,302,307 (moved) et 412,416 - les 304 le sont dans le backing 
  1542.         // ------------------------------------------------------------
  1543.         if ( (r.statuscode==301) 
  1544.           || (r.statuscode==302)
  1545.           || (r.statuscode==303)
  1546.           || (r.statuscode==307)
  1547.           ) {          
  1548.           //if (r.adr!=NULL) {   // adr==null si fichier direct. [catch: davename normalement si cgi]
  1549.             //int i=0;
  1550.             char *rn=NULL;
  1551.             char* p;
  1552.             
  1553.             if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  1554.             //if (opt.errlog) {
  1555.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"%s for %s%s"LF,r.msg,urladr,urlfil);
  1556.               test_flush;
  1557.             }
  1558.             
  1559.             
  1560. #if 0
  1561.             //do {
  1562.             //  if (strfield(r.adr+i,"href=")) {    // URL trouvΘe
  1563. #endif
  1564.             {
  1565.               char mov_url[HTS_URLMAXSIZE*2],mov_adr[HTS_URLMAXSIZE*2],mov_fil[HTS_URLMAXSIZE*2];
  1566.               int n=0;
  1567.               int reponse=0;
  1568.               mov_url[0]='\0'; mov_adr[0]='\0'; mov_fil[0]='\0';
  1569.               //
  1570.               //printf("location panic! %s\n",r.location);
  1571.               
  1572.               ////p=r.adr+i;
  1573.               ////p+=5;    // sauter href
  1574.               p=r.location;
  1575.               while(is_space(*p)) p++;  // sauter espaces, " & cie
  1576.               while((!is_space(p[n])) && (p[n] != 0) && (p[n] != '>')) n++;  // compter caractΦres
  1577.               strcpy (mov_url,"");
  1578.               strncat(mov_url,p,n);    // copier URL
  1579.               
  1580.               // url qque -> adresse+fichier
  1581.               if ((reponse=ident_url_relatif(mov_url,urladr,urlfil,mov_adr,mov_fil))>=0) {                        
  1582.                 int get_it=0;         // ne pas prendre le fichier α la mΩme adresse par dΘfaut
  1583.                 int set_prio_to=0;    // pas de priotitΘ fixΘd par wizard
  1584.                 
  1585.                 //if (ident_url(mov_url,mov_adr,mov_fil)!=-1) {    // ok URL reconnue
  1586.                 // c'est (en gros) la mΩme URL..
  1587.                 // si c'est un problΦme de casse dans le host c'est que le serveur est buggΘ
  1588.                 // ("RFC says.." : host name IS case insensitive)
  1589.                 if ((strfield2(mov_adr,urladr)!=0) && (strfield2(mov_fil,urlfil)!=0)) {  // identique α casse prΦs
  1590.                   // on tourne en rond
  1591.                   if (strcmp(mov_fil,urlfil)==0) {
  1592.                     error=1;
  1593.                     get_it=-1;        // ne rien faire
  1594.                     if (opt.errlog) {
  1595.                       fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Can not bear crazy server (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1596.                       test_flush;
  1597.                     }
  1598.                   } else {    // mauvaise casse, effacer entrΘe dans la pile et rejouer une fois
  1599.                     get_it=1;
  1600.                   }
  1601.                 } else {
  1602.                   if (ishtml(mov_url)==0) {   // pas mΩme adresse MAIS c'est un fichier (pas de page moved possible)
  1603.                     // -> on prend α cette adresse, le lien sera enregistrΘ avec lien_record() (hash)
  1604.                     if ((opt.debug>1) && (opt.log!=NULL)) {
  1605.                       fspc(opt.log,"debug"); fprintf(opt.log,"wizard link test for moved file at %s%s.."LF,mov_adr,mov_fil);
  1606.                       test_flush;
  1607.                     }
  1608.                     if (hts_acceptlink(&opt,ptr,lien_tot,liens,
  1609.                       mov_adr,mov_fil,
  1610.                       filters,&filptr,filter_max,
  1611.                       &robots,
  1612.                       &set_prio_to,
  1613.                       NULL) != 1) {                /* nouvelle adresse non refusΘe ? */
  1614.                       get_it=1;
  1615.                       if ((opt.debug>1) && (opt.log!=NULL)) {
  1616.                         fspc(opt.log,"debug"); fprintf(opt.log,"moved link accepted: %s%s"LF,mov_adr,mov_fil);
  1617.                         test_flush;
  1618.                       }
  1619.                     }
  1620.                   } /* sinon traitΘ normalement */
  1621.                 }
  1622.                 
  1623.                 //if ((strfield2(mov_adr,urladr)!=0) && (strfield2(mov_fil,urlfil)!=0)) {  // identique α casse prΦs
  1624.                 if (get_it==1) {
  1625.                   // court-circuiter le reste du traitement
  1626.                   // et reculer pour mieux sauter
  1627.                   if (opt.errlog) {
  1628.                     fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Warning wrong case ignored for %s%s (real one is %s%s)"LF,urladr,urlfil,mov_adr,mov_fil);
  1629.                     test_flush;
  1630.                   }          
  1631.                   // canceller lien actuel
  1632.                   error=1;
  1633.                   strcpy(liens[ptr]->adr,"!");  // caractΦre bidon (invalide hash)
  1634. #if HTS_HASH
  1635. #else
  1636.                   liens[ptr]->sav_len=-1;       // taille invalide
  1637. #endif
  1638.                   // noter NOUVEAU lien
  1639.                   {
  1640.                     char mov_sav[HTS_URLMAXSIZE*2];
  1641.                     // calculer lien et Θventuellement modifier addresse/fichier
  1642.                     if (url_savename(mov_adr,mov_fil,mov_sav,NULL,NULL,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe)!=-1) { 
  1643.                       if (hash_read(&hash,mov_sav,"",0)<0) {      // n'existe pas dΘja
  1644.                         // enregistrer lien (MACRO) avec SAV IDENTIQUE
  1645.                         liens_record(mov_adr,mov_fil,liens[ptr]->sav,"","");
  1646.                         //liens_record(mov_adr,mov_fil,mov_sav,"","");
  1647.                         if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1648.                           // mode test?
  1649.                           liens[lien_tot]->testmode=liens[ptr]->testmode;
  1650.                           liens[lien_tot]->link_import=0;       // mode normal
  1651.                           if (!set_prio_to)
  1652.                             liens[lien_tot]->depth=liens[ptr]->depth;
  1653.                           else
  1654.                             liens[lien_tot]->depth=max(0,min(set_prio_to-1,liens[ptr]->depth));       // PRIORITE NULLE (catch page)
  1655.                           liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  1656.                           liens[lien_tot]->retry=liens[ptr]->retry;
  1657.                           liens[lien_tot]->premier=liens[ptr]->premier;
  1658.                           liens[lien_tot]->precedent=liens[ptr]->precedent;
  1659.                           lien_tot++;
  1660.                         } else {  // oups erreur, plus de mΘmoire!!
  1661.                           printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1662.                           if (opt.errlog) {
  1663.                             fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1664.                             test_flush;
  1665.                           }
  1666.                           //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1667.                           XH_uninit;    // dΘsallocation mΘmoire & buffers
  1668.                           return 0;
  1669.                         }
  1670.                       } else {
  1671.                         if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  1672.                           fspc(opt.errlog,"warning"); fprintf(opt.errlog,"moving %s to an existing file %s"LF,liens[ptr]->fil,urlfil);
  1673.                           test_flush;
  1674.                         }
  1675.                       }
  1676.                       
  1677.                     }
  1678.                   }
  1679.                   
  1680.                   //printf("-> %s %s %s\n",liens[lien_tot-1]->adr,liens[lien_tot-1]->fil,liens[lien_tot-1]->sav);
  1681.                   
  1682.                   // note mΘtaphysique: il se peut qu'il y ait un index.html et un INDEX.HTML
  1683.                   // sous DOS ca marche pas trΦs bien... mais comme je suis gΘnial url_savename()
  1684.                   // est α mΩme de rΘgler ce problΦme
  1685.                 } else if (get_it==0) {    // adresse vraiment diffΘrente et potentiellement en html (pas de possibilitΘ de bouger la page tel quel α cause des <img src..> et cie)
  1686.                   rn=(char*) calloct(8192,1);
  1687.                   if (rn!=NULL) {
  1688.                     // On prΘpare une page qui sautera immΘdiatement sur la bonne URL
  1689.                     // Le scanner re-changera, ensuite, cette URL, pour la mirrorer!
  1690.                     strcpy(rn,"<HTML>"CRLF);
  1691.                     strcat(rn,"<!-- Created by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->"CRLF);
  1692.                     strcat(rn,"<HEAD>"CRLF"<TITLE>Page has moved</TITLE>"CRLF"</HEAD>"CRLF"<BODY>"CRLF);
  1693.                     strcat(rn,"<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; URL=");
  1694.                     strcat(rn,mov_url);    // URL
  1695.                     strcat(rn,"\">"CRLF);
  1696.                     strcat(rn,"<A HREF=\"");
  1697.                     strcat(rn,mov_url);
  1698.                     strcat(rn,"\">");
  1699.                     strcat(rn,"<B>Click here...</B></A>"CRLF);
  1700.                     strcat(rn,"</BODY>"CRLF);
  1701.                     strcat(rn,"<!-- Created by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->"CRLF);
  1702.                     strcat(rn,"</HTML>"CRLF);
  1703.                     
  1704.                     // changer la page
  1705.                     if (r.adr) { freet(r.adr); r.adr=NULL; }
  1706.                     r.adr=rn;
  1707.                     r.size=strlen(r.adr);
  1708.                     strcpy(r.contenttype,"text/html");
  1709.                     if (opt.errlog) {
  1710.                       fspc(opt.errlog,"warning"); fprintf(opt.errlog,"File has moved from %s%s to %s"LF,urladr,urlfil,mov_url);
  1711.                       test_flush;
  1712.                     }
  1713.  
  1714.                     // dΘclarer page comme α Θcraser par le fichier si fichier binaire
  1715.                     // on va donc modifier la structure physique du site
  1716.                     // MAIS, en cas d'update, cela fonctionnera, car:
  1717.                     // 1. page moved: pas en cache (moved)
  1718.                     // 2. fichier qui Θcrase: mΩme en cas de get avec range:, comme c'est une erreur il 
  1719.                     // n'y aura pas de rΘponse "partial content"
  1720.                     /*
  1721.                     if (ishtml(mov_url)==0) {
  1722.                       if (!fexist(fconcat(opt.path_log,"moved.lst"))) {
  1723.                         FILE* fp=fopen(fconcat(opt.path_log,"moved.lst"),"wb");
  1724.                         if (fp) fclose(fp);
  1725.                       }
  1726.                       {
  1727.                         FILE* fp=fopen(fconcat(opt.path_log,"moved.lst"),"ab");
  1728.                         if (fp) {
  1729.                           fprintf(fp,"%s\n",mov_url);
  1730.                           fclose(fp);
  1731.                         }
  1732.                       }
  1733.                     }
  1734.                     */
  1735.  
  1736.                   }
  1737.                 }
  1738.               } else {
  1739.                 if (opt.errlog) {
  1740.                   fspc(opt.errlog,"error");
  1741.                   if (reponse==-2)
  1742.                     fprintf(opt.errlog,"Protocol ftp:// not supported for %s in file %s"LF,urladr,urlfil);
  1743.                   else
  1744.                     fprintf(opt.errlog,"Unrecoverable %s for %s%s (error move to %s)"LF,r.msg,urladr,urlfil,mov_url);
  1745.                   test_flush;
  1746.                 }
  1747.                 error=1;    // URL non reconnue
  1748.               }
  1749.             }
  1750. #if 0
  1751.             // i++;
  1752.             //} while((i<r.size) && (rn==NULL) && (error==0));
  1753. #endif
  1754.                       
  1755.           // erreur HTTP (ex: 404, not found)
  1756.         } else if (   (r.statuscode==412)
  1757.                    || (r.statuscode==416)
  1758.           ) {    // Precondition Failed, c'est α dire pour nous redemander TOUT le fichier
  1759.           if (fexist(liens[ptr]->sav)) {
  1760.             remove(liens[ptr]->sav);    // Eliminer
  1761.             if (!fexist(liens[ptr]->sav)) {  // Bien ΘliminΘ? (sinon on boucle..)
  1762. #if HDEBUG
  1763.               printf("Partial content NOT up-to-date, reget all file for %s\n",liens[ptr]->sav);
  1764. #endif
  1765.               if ( (opt.debug>1) && (opt.errlog!=NULL) ) {
  1766.                 //if (opt.errlog) {
  1767.                 fspc(opt.errlog,"debug"); fprintf(opt.errlog,"Partial file reget (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1768.                 test_flush;
  1769.               }
  1770.               // enregistrer le MEME lien (MACRO)
  1771.               liens_record(liens[ptr]->adr,liens[ptr]->fil,liens[ptr]->sav,"","");
  1772.               if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1773.                 liens[lien_tot]->testmode=liens[ptr]->testmode;          // mode test?
  1774.                 liens[lien_tot]->link_import=0;       // pas mode import
  1775.                 liens[lien_tot]->depth=liens[ptr]->depth;
  1776.                 liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  1777.                 liens[lien_tot]->retry=liens[ptr]->retry;
  1778.                 liens[lien_tot]->premier=liens[ptr]->premier;
  1779.                 liens[lien_tot]->precedent=ptr;
  1780.                 lien_tot++;
  1781.                 //
  1782.                 // canceller lien actuel
  1783.                 error=1;
  1784.                 strcpy(liens[ptr]->adr,"!");  // caractΦre bidon (invalide hash)
  1785. #if HTS_HASH
  1786. #else
  1787.                 liens[ptr]->sav_len=-1;       // taille invalide
  1788. #endif
  1789.                 //
  1790.               } else {  // oups erreur, plus de mΘmoire!!
  1791.                 printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1792.                 if (opt.errlog) {
  1793.                   fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1794.                   test_flush;
  1795.                 }
  1796.                 //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1797.                 XH_uninit;    // dΘsallocation mΘmoire & buffers
  1798.                 return 0;
  1799.               } 
  1800.             } else {
  1801.               if (opt.errlog!=NULL) {
  1802.                 fspc(opt.errlog,"error"); fprintf(opt.errlog,"Can not remove old file %s"LF,urlfil);
  1803.                 test_flush;
  1804.               }
  1805.             }
  1806.           } else {
  1807.             if (opt.errlog!=NULL) {
  1808.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Unexpected 412/416 error (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1809.               test_flush;
  1810.             }
  1811.           }
  1812.         } else if (r.statuscode!=200) {
  1813.           int can_retry=0;
  1814.  
  1815.           // cas o∙ l'on peut reessayer
  1816.           // -2=timeout -3=rateout (interne α httrack)
  1817.           switch(r.statuscode) {
  1818.           //case -1: can_retry=1; break;
  1819.           case -2: if (opt.hostcontrol) {    // timeout et retry ΘpuisΘs
  1820.             if ((opt.hostcontrol & 1) && (liens[ptr]->retry<=0)) {
  1821.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1822.                 fspc(opt.log,"debug"); fprintf(opt.log,"Link banned: %s%s"LF,urladr,urlfil); test_flush;
  1823.               }
  1824.               host_ban(&opt,liens,ptr,lien_tot,back,back_max,filters,filter_max,&filptr,jump_identification(urladr));
  1825.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1826.                 fspc(opt.log,"debug"); fprintf(opt.log,"Info: previous log - link banned: %s%s"LF,urladr,urlfil); test_flush;
  1827.               }
  1828.             } else can_retry=1;
  1829.                    } else can_retry=1;
  1830.             break;
  1831.           case -3: if ((opt.hostcontrol) && (liens[ptr]->retry<=0)) {    // too slow
  1832.             if (opt.hostcontrol & 2) {
  1833.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1834.                 fspc(opt.log,"debug"); fprintf(opt.log,"Link banned: %s%s"LF,urladr,urlfil); test_flush;
  1835.               }
  1836.               host_ban(&opt,liens,ptr,lien_tot,back,back_max,filters,filter_max,&filptr,jump_identification(urladr));
  1837.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1838.                 fspc(opt.log,"debug"); fprintf(opt.log,"Info: previous log - link banned: %s%s"LF,urladr,urlfil); test_flush;
  1839.               }
  1840.             } else can_retry=1;
  1841.                    } else can_retry=1;
  1842.             break;
  1843.           case -4:            // connect closed
  1844.             can_retry=1;
  1845.             break;
  1846.           case -5:            // other (non fatal) error
  1847.             can_retry=1;
  1848.             break;
  1849.           case 408: case 409: case 500: case 502: case 504: can_retry=1;
  1850.             break;
  1851.           }
  1852.           
  1853.           if ( strcmp(liens[ptr]->fil,"/primary") ) {    // pas primary (page 0)
  1854.             if ((liens[ptr]->retry<=0) || (!can_retry) ) {  // retry ΘpuisΘs (ou retry impossible)
  1855.               if (opt.errlog) {
  1856.                 if ((opt.retry>0) && (can_retry)){
  1857.                   fspc(opt.errlog,"error"); 
  1858.                   fprintf(opt.errlog,"\"%s\" (%d) after %d retries at link %s%s (from %s%s)"LF,r.msg,r.statuscode,opt.retry,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1859.                 } else {
  1860.                   if (r.statuscode==-10) {    // test OK
  1861.                     if ((opt.debug>0) && (opt.errlog!=NULL)) {
  1862.                       fspc(opt.errlog,"info"); 
  1863.                       fprintf(opt.errlog,"Test OK at link %s%s (from %s%s)"LF,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1864.                     }
  1865.                   } else {
  1866.                     if (strcmp(urlfil,"/robots.txt")) {       // ne pas afficher d'infos sur robots.txt par dΘfaut
  1867.                       fspc(opt.errlog,"error"); 
  1868.                       fprintf(opt.errlog,"\"%s\" (%d) at link %s%s (from %s%s)"LF,r.msg,r.statuscode,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1869.                     } else {
  1870.                       if (opt.debug>0) {  // on fera un alert si le retry Θchoue               
  1871.                         fspc(opt.errlog,"info"); fprintf(opt.errlog,"No robots.txt rules at %s"LF,urladr);
  1872.                         test_flush;
  1873.                       }
  1874.                     }
  1875.                   }
  1876.                 }
  1877.                 test_flush;
  1878.               }
  1879.               
  1880.               // ici on teste si on doit enregistrer la page tout de mΩme
  1881.               if (opt.errpage) {
  1882.                 // NO error in trop level
  1883.                 // due to the "no connection -> previous restored" hack
  1884.                 if (liens[ptr]->precedent != 0) {
  1885.                   store_errpage=1;
  1886.                 }
  1887.               }
  1888.               
  1889.             } else {    // retry!!
  1890.               if (opt.debug>0) {  // on fera un alert si le retry Θchoue               
  1891.                 fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Retry after error %d (%s) at link %s%s (from %s%s)"LF,r.statuscode,r.msg,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1892.                 test_flush;
  1893.               }
  1894.               // redemander fichier
  1895.               liens_record(urladr,urlfil,savename,"","");
  1896.               if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1897.                 liens[lien_tot]->testmode=liens[ptr]->testmode;          // mode test?
  1898.                 liens[lien_tot]->link_import=0;       // pas mode import
  1899.                 liens[lien_tot]->depth=liens[ptr]->depth;
  1900.                 liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  1901.                 liens[lien_tot]->retry=liens[ptr]->retry-1;    // moins 1 retry!
  1902.                 liens[lien_tot]->premier=liens[ptr]->premier;
  1903.                 liens[lien_tot]->precedent=liens[ptr]->precedent;
  1904.                 lien_tot++;
  1905.               } else {  // oups erreur, plus de mΘmoire!!
  1906.                 printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1907.                 if (opt.errlog) {
  1908.                   fspc(opt.errlog,"panic"); 
  1909.                   fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1910.                   test_flush;
  1911.                 }
  1912.                 //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1913.                 XH_uninit;    // dΘsallocation mΘmoire & buffers
  1914.                 return 0;
  1915.               } 
  1916.             }
  1917.           } else {
  1918.             if (opt.errlog) {
  1919.               fspc(opt.errlog,"info"); 
  1920.               fprintf(opt.errlog,"Info: no robots.txt at %s%s"LF,urladr,urlfil);
  1921.             }
  1922.           }
  1923.           if (!store_errpage) {
  1924.             if (r.adr) { freet(r.adr); r.adr=NULL; }  // dΘsalloc
  1925.             error=1;  // erreur!
  1926.           }
  1927.         }
  1928.         // FIN rattrapage des 301,302,307..
  1929.         // ------------------------------------------------------------
  1930.         
  1931.         
  1932.  
  1933.       }  // if !error
  1934.     }  // if !error
  1935.     
  1936.     if (!error) {  
  1937. #if DEBUG_SHOWTYPES
  1938.       if (strstr(REG,r.contenttype)==NULL) {
  1939.         strcat(REG,r.contenttype);
  1940.         strcat(REG,"\n");
  1941.         printf("%s\n",r.contenttype);
  1942.         io_flush;
  1943.       }
  1944. #endif
  1945.       
  1946.  
  1947.       // ------------------------------------------------------
  1948.       // ok, fichier chargΘ localement
  1949.       // ------------------------------------------------------
  1950.       
  1951.       // VΘrificateur d'intΘgritΘ
  1952.       #if DEBUG_CHECKINT
  1953.       {
  1954.         int i;
  1955.         for(i=0;i<back_max;i++) {
  1956.           char si[256];
  1957.           sprintf(si,"Test global aprΦs back_wait, index %d",i);
  1958.           _CHECKINT(&back[i],si)
  1959.         }
  1960.       }
  1961.       #endif
  1962.  
  1963.  
  1964.       /* info: updated */
  1965.       if (ptr>0) {
  1966.         // "mis α jour"
  1967.         if ((!r.notmodified) && (opt.is_update) && (!store_errpage)) {    // page modifiΘe
  1968.           if (strnotempty(savename)) {
  1969.             HTS_STAT.stat_updated_files++;
  1970.             if (opt.log!=NULL) {
  1971.               //if ((opt.debug>0) && (opt.log!=NULL)) {
  1972.               fspc(opt.log,"info"); fprintf(opt.log,"File updated: %s%s"LF,urladr,urlfil);
  1973.               test_flush;
  1974.             }
  1975.           }
  1976.         } else {
  1977.           if (!store_errpage) {
  1978.             if ( (opt.debug>0) && (opt.log!=NULL) ) {
  1979.               fspc(opt.log,"info"); fprintf(opt.log,"File recorded: %s%s"LF,urladr,urlfil);
  1980.               test_flush;
  1981.             }
  1982.           }
  1983.         }
  1984.       }
  1985.       
  1986.       // ------------------------------------------------------
  1987.       // traitement (parsing)
  1988.       // ------------------------------------------------------
  1989.  
  1990.       // traiter
  1991.       if (
  1992.            ( (is_hypertext_mime(r.contenttype))   /* Is HTML or Js, .. */
  1993.              || (may_be_hypertext_mime(r.contenttype) && (r.adr) )  /* Is real media, .. */
  1994.            )
  1995.         && (liens[ptr]->depth>0)            /* Depth > 0 (recurse depth) */
  1996.         && (r.adr!=NULL)        /* HTML Data exists */
  1997.         && (r.size>0)           /* And not empty */
  1998.         && (!store_errpage)     /* Not an html error page */
  1999.         && (savename[0]!='\0')  /* Output filename exists */
  2000.       ) {    // ne traiter que le html si autorisΘ
  2001.         // -- -- -- --
  2002.         // Parsing HTML
  2003.         if (!error) {
  2004.           // I'll have to segment this part
  2005. #include "htsparse.c"
  2006.         }
  2007.         // Fin parsing HTML
  2008.         // -- -- -- --
  2009.  
  2010.  
  2011.       }  // si text/html
  2012.       // -- -- --
  2013.       else {    // sauver fichier quelconque
  2014.         // -- -- --
  2015.         // sauver fichier
  2016.  
  2017.  
  2018.         /* En cas d'erreur, vΘrifier que fichier d'erreur existe */
  2019.         if (strnotempty(savename) == 0) {           // chemin de sauvegarde existant
  2020.           if (strcmp(urlfil,"/robots.txt")==0) {    // pas robots.txt
  2021.             if (store_errpage) {                    // c'est une page d'erreur
  2022.               int create_html_warning=0;
  2023.               int create_gif_warning=0;
  2024.               switch (ishtml(urlfil)) {      /* pas fichier html */
  2025.               case 0:                        /* non html */
  2026.                 {
  2027.                   char buff[256];
  2028.                   guess_httptype(buff,urlfil);
  2029.                   if (strcmp(buff,"image/gif")==0)
  2030.                     create_gif_warning=1;
  2031.                 }
  2032.                 break;
  2033.               case 1:                        /* html */
  2034.                 if (!r.adr) {
  2035.                 }
  2036.                 break;
  2037.               default:                       /* don't know.. */
  2038.                 break;    
  2039.               }
  2040.               /* CrΘer message d'erreur ? */
  2041.               if (create_html_warning) {
  2042.                 char* adr=(char*)malloc(strlen(HTS_DATA_ERROR_HTML)+1100);
  2043.                 if ( (opt.debug>0) && (opt.log!=NULL) ) {
  2044.                   fspc(opt.log,"info"); fprintf(opt.log,"Creating HTML warning file (%s)"LF,r.msg);
  2045.                   test_flush;
  2046.                 }
  2047.                 if (adr) {
  2048.                   if (r.adr) {
  2049.                     freet(r.adr);
  2050.                     r.adr=NULL;
  2051.                   }
  2052.                   sprintf(adr,HTS_DATA_ERROR_HTML,r.msg);
  2053.                   r.adr=adr;
  2054.                 }
  2055.               } else if (create_gif_warning) {
  2056.                 char* adr=(char*)malloc(HTS_DATA_UNKNOWN_GIF_LEN);
  2057.                 if ( (opt.debug>0) && (opt.log!=NULL) ) {
  2058.                   fspc(opt.log,"info"); fprintf(opt.log,"Creating GIF dummy file (%s)"LF,r.msg);
  2059.                   test_flush;
  2060.                 }
  2061.                 if (r.adr) {
  2062.                   freet(r.adr);
  2063.                   r.adr=NULL;
  2064.                 }
  2065.                 bcopy(HTS_DATA_UNKNOWN_GIF,adr,HTS_DATA_UNKNOWN_GIF_LEN);
  2066.                 r.adr=adr;
  2067.               }
  2068.             }
  2069.           }
  2070.         }
  2071.  
  2072.         if (strnotempty(savename) == 0) {    // pas de chemin de sauvegarde
  2073.           if (strcmp(urlfil,"/robots.txt")==0) {    // robots.txt
  2074.             if (r.adr) {
  2075.               int bptr=0;
  2076.               char line[256];
  2077.               char buff[8192];
  2078.               char infobuff[8192];
  2079.               int record=0;
  2080.               line[0]='\0'; buff[0]='\0'; infobuff[0]='\0';
  2081.               //
  2082. #if DEBUG_ROBOTS
  2083.               printf("robots.txt dump:\n%s\n",r.adr);
  2084. #endif
  2085.               do {
  2086.                 bptr+=binput(r.adr+bptr,line,200);
  2087.                 if (strfield(line,"user-agent:")) {
  2088.                   char* a;
  2089.                   a=line+11;
  2090.                   while(*a==' ') a++;    // sauter espace(s)
  2091.                   if (*a == '*') {
  2092.                     if (record != 2)
  2093.                       record=1;    // c pour nous
  2094.                   } else if (strfield(a,"httrack")) {
  2095.                     buff[0]='\0';      // re-enregistrer
  2096.                     infobuff[0]='\0';
  2097.                     record=2;          // locked
  2098. #if DEBUG_ROBOTS
  2099.                     printf("explicit disallow for httrack\n");
  2100. #endif
  2101.                   }
  2102.                   else record=0;
  2103.                 } else if (record) {
  2104.                   if (strfield(line,"disallow:")) {
  2105.                     char* a;
  2106.                     a=strchr(line,'#');
  2107.                     if (a) *a='\0';
  2108.                     while((line[strlen(line)-1]==' ') || (line[strlen(line)-1]==10) || (line[strlen(line)-1]==13))
  2109.                       line[strlen(line)-1]='\0';   // supprimer espaces
  2110.                     a=line+9;
  2111.                     while((*a==' ') || (*a==10) || (*a==13))
  2112.                       a++;    // sauter espace(s)
  2113.                     if (strnotempty(a)) {
  2114.                       if (strcmp(a,"/")) {      /* ignoring disallow: / */
  2115.                         strcat(buff,a);
  2116.                         strcat(buff,"\n");
  2117.                         if (strnotempty(infobuff)) strcat(infobuff,", ");
  2118.                         strcat(infobuff,a);
  2119.                       } else {
  2120.                         if (opt.errlog!=NULL) {
  2121.                           fspc(opt.errlog,"info"); fprintf(opt.errlog,"Note: %s robots.txt rules are too restrictive, ignoring /"LF,urladr);
  2122.                           test_flush;
  2123.                         }
  2124.                       }
  2125.                     }
  2126.                   }
  2127.                 }
  2128.               } while( (bptr<r.size) && (strlen(buff)<4096) );
  2129.               if (strnotempty(buff)) {
  2130.                 checkrobots_set(&robots,urladr,buff);
  2131.                 if (opt.log!=NULL) {
  2132.                   if (opt.log != opt.errlog) {
  2133.                     fspc(opt.log,"info"); fprintf(opt.log,"Note: robots.txt forbidden links for %s are: %s"LF,urladr,infobuff);
  2134.                     test_flush;
  2135.                   } 
  2136.                 }
  2137.                 if (opt.errlog!=NULL) {
  2138.                   fspc(opt.errlog,"info"); fprintf(opt.errlog,"Note: due to %s remote robots.txt rules, links begining with these path will be forbidden: %s (see in the options to disable this)"LF,urladr,infobuff);
  2139.                   test_flush;
  2140.                 }
  2141.               }
  2142.             }
  2143.           }
  2144.         } else if (r.is_write) {    // dΘja sauvΘ sur disque
  2145.           if (!ishttperror(r.statuscode))
  2146.             HTS_STAT.stat_files++;
  2147.           HTS_STAT.stat_bytes+=r.size;
  2148.           //printf("ok......\n");
  2149.         } else {
  2150.           // Si on doit sauver une page HTML sans la scanner, cela signifie que le niveau de
  2151.           // rΘcursion nous en empΩche
  2152.           // Dans ce cas on met un fichier indiquant ce fait
  2153.           // Si par la suite on doit retraiter ce fichier avec un niveau de rΘcursion plus
  2154.           // fort, on supprimera le readme, et on scannera le fichier html!
  2155.           // note: sautΘ si store_errpage (cαd si page d'erreur, non α scanner!)
  2156.           if ( (is_hypertext_mime(r.contenttype)) && (!store_errpage) && (r.size>0)) {  // c'est du html!!
  2157.             char tempo[HTS_URLMAXSIZE*2];
  2158.             FILE* fp;
  2159.             tempo[0]='\0';
  2160.             strcpy(tempo,savename);
  2161.             strcat(tempo,".readme");
  2162.             
  2163. #if HTS_DOSNAME
  2164.             // remplacer / par des slash arriΦre
  2165.             {
  2166.               int i=0;
  2167.               while(tempo[i]) {
  2168.                 if (tempo[i]=='/')
  2169.                   tempo[i]='\\';
  2170.                 i++;
  2171.               } 
  2172.             } 
  2173.             // a partir d'ici le slash devient antislash
  2174. #endif
  2175.             
  2176.             if ((fp=fopen(tempo,"wb"))!=NULL) {
  2177.               fprintf(fp,"Info-file generated by HTTrack Website Copier "HTTRACK_VERSION""CRLF""CRLF);
  2178.               fprintf(fp,"The file %s has not been scanned by HTS"CRLF,savename);
  2179.               fprintf(fp,"Some links contained in it may be unreachable locally."CRLF);
  2180.               fprintf(fp,"If you want to get these files, you have to set an upper recurse level, ");
  2181.               fprintf(fp,"and to rescan the URL."CRLF);
  2182.               fclose(fp);
  2183. #if HTS_WIN==0
  2184.               chmod(tempo,HTS_ACCESS_FILE);      
  2185. #endif
  2186.               usercommand(0,NULL,antislash(tempo));
  2187.             }
  2188.             
  2189.             
  2190.             if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  2191.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Warning: store %s without scan: %s"LF,r.contenttype,savename);
  2192.               test_flush;
  2193.             }
  2194.           } else {
  2195.             if ((opt.getmode & 2)!=0) {    // ok autorisΘ
  2196.               if ( (opt.debug>1) && (opt.log!=NULL) ) {
  2197.                 fspc(opt.log,"debug"); fprintf(opt.log,"Store %s: %s"LF,r.contenttype,savename);
  2198.                 test_flush;
  2199.               }
  2200.             } else {    // lien non autorisΘ! (ex: cgi-bin en html)
  2201.               if ((opt.debug>1) && (opt.log!=NULL)) {
  2202.                 fspc(opt.log,"debug"); fprintf(opt.log,"non-html file ignored after upload at %s : %s"LF,urladr,urlfil);
  2203.                 test_flush;
  2204.               } 
  2205.               freet(r.adr); r.adr=NULL;
  2206.             }
  2207.           }
  2208.           
  2209.           //printf("extern=%s\n",r.contenttype);
  2210.  
  2211.           // ATTENTION C'EST ICI QU'ON SAUVE LE FICHIER!!          
  2212.           if (r.adr) {
  2213.             if (filesave(r.adr,(int)r.size,savename)!=0) {
  2214.               if (opt.errlog) {   
  2215.                 fprintf(opt.errlog,"Unable to save file %s"LF,savename);
  2216.                 test_flush;
  2217.               }
  2218.             } else {
  2219.               if (!ishttperror(r.statuscode))
  2220.                 HTS_STAT.stat_files++;
  2221.               HTS_STAT.stat_bytes+=r.size;
  2222.             }
  2223.           }
  2224.           
  2225.         }
  2226.   
  2227.  
  2228.         /* Parsing of other media types (java, ram..) */
  2229.         /*
  2230.         if (strfield2(r.contenttype,"audio/x-pn-realaudio")) {
  2231.           if ((opt.debug>1) && (opt.log!=NULL)) {
  2232.             fspc(opt.log,"debug"); fprintf(opt.log,"(Real Media): parsing %s"LF,savename); test_flush;
  2233.           }
  2234.           if (fexist(savename)) {   // ok, existe bien!
  2235.             FILE* fp=fopen(savename,"r+b");
  2236.             if (fp) {
  2237.               if (!fseek(fp,0,SEEK_SET)) {
  2238.                 char line[HTS_URLMAXSIZE*2];
  2239.                 linput(fp,line,HTS_URLMAXSIZE);
  2240.                 if (strnotempty(line)) {
  2241.                   if ((opt.debug>1) && (opt.log!=NULL)) {
  2242.                     fspc(opt.log,"debug"); fprintf(opt.log,"(Real Media): detected %s"LF,line); test_flush;
  2243.                   }
  2244.                 }
  2245.               }
  2246.               fclose(fp);
  2247.             }
  2248.           }
  2249.         } else */
  2250.         if (opt.parsejava) {
  2251.           if (strlen(savename)>6) {  // fichier.class
  2252.             if (strfield(savename+strlen(savename)-6,".class")) {  // ok c'est une classe
  2253.               if (fexist(savename)) {   // ok, existe bien!
  2254.                 char err_msg[1100];
  2255.                 int r;
  2256.                 err_msg[0]='\0';
  2257.                 
  2258.                 //##char* buffer;
  2259.                 // JavaParsing f34R!
  2260.                 if ((opt.debug>1) && (opt.log!=NULL)) {
  2261.                   fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): parsing %s"LF,savename); test_flush;
  2262.                 }
  2263.                 
  2264.                 //##buffer=(char*) malloct(32768);
  2265.                 //##if (buffer) {
  2266.                 //
  2267.                 //##strcpy(buffer,"$BUFFER$");
  2268.                 //##hts_add_file(buffer);    // dΘclarer buffer
  2269.                 while(hts_add_file(NULL,-1) >= 0);   // clear chain
  2270.                 
  2271.                 r=hts_parse_java(savename,(char*) &err_msg);  // parsing
  2272.                 if (!r) {    // error
  2273.                   if (opt.errlog) {   
  2274.                     fprintf(opt.errlog,"Unable to parse java file %s : %s"LF,savename,err_msg);
  2275.                     test_flush;
  2276.                   }
  2277.                 } else {  // ok
  2278.                   char adr[HTS_URLMAXSIZE*2],fil[HTS_URLMAXSIZE*2],save[HTS_URLMAXSIZE*2];  // nom du fichier α sauver dans la boucle
  2279.                   char codebase[HTS_URLMAXSIZE*2];                  // codebase classe java
  2280.                   char lien[HTS_URLMAXSIZE*2];
  2281.                   //##char* a;
  2282.                   int file_position;
  2283.                   int pass_fix,prio_fix;
  2284.                   codebase[0]='\0';
  2285.                   //
  2286.                   
  2287.                   if ((opt.debug>1) && (opt.log!=NULL)) {
  2288.                     fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): parsing finished, now copying links.."LF); test_flush;
  2289.                   }
  2290.                   // recopie de "creer le lien"
  2291.                   //
  2292.                   
  2293.                   // adr = c'est la mΩme
  2294.                   // fil et save: save2 et fil2
  2295.                   prio_fix=maximum(liens[ptr]->depth-1,0);
  2296.                   pass_fix=max(liens[ptr]->pass2,numero_passe);
  2297.                   if (liens[ptr]->cod) strcpy(codebase,liens[ptr]->cod);       // codebase valable pour tt les classes descendantes
  2298.                   if (strnotempty(codebase)==0) {    // pas de codebase, construire
  2299.                     char* a;
  2300.                     strcpy(codebase,liens[ptr]->fil);
  2301.                     a=codebase+strlen(codebase)-1;
  2302.                     while((*a) && (*a!='/') && ((int) a > (int) codebase)) a--;
  2303.                     if (*a=='/')
  2304.                       *(a+1)='\0';    // couper
  2305.                   } else {    // couper http:// Θventuel
  2306.                     if (strfield(codebase,"http://")) {
  2307.                       char tempo[HTS_URLMAXSIZE*2];
  2308.                       char* a=codebase+7;
  2309.                       a=strchr(a,'/');    // aprΦs host
  2310.                       if (a) {  // ** msg erreur et vΘrifier?
  2311.                         strcpy(tempo,a);
  2312.                         strcpy(codebase,tempo);    // couper host
  2313.                       } else {
  2314.                         if (opt.errlog) {   
  2315.                           fprintf(opt.errlog,"Unexpected strstr error in base %s"LF,codebase);
  2316.                           test_flush;
  2317.                         }
  2318.                       }
  2319.                     }
  2320.                   }
  2321.                   //##a=buffer;
  2322.                   //##strcat(buffer,"&");  // fin du buffer
  2323.                   if (!((int) strlen(codebase)<HTS_URLMAXSIZE)) {    // trop long
  2324.                     if (opt.errlog) {   
  2325.                       fprintf(opt.errlog,"Codebase too long, parsing skipped (%s)"LF,codebase);
  2326.                       test_flush;
  2327.                     }
  2328.                     //##a=NULL;
  2329.                     while(hts_add_file(NULL,-1) >= 0);   // clear chain
  2330.                   }
  2331.                   while ( (file_position=hts_add_file(lien,-1)) >= 0 ) {
  2332.                     int dejafait=0;
  2333.                     /* //##
  2334.                     char* b;
  2335.                     
  2336.                      // prochain fichier α noter!
  2337.                      lien[0]='\0';
  2338.                      b=strchr(a,'&');  // marqueur de fin de chaine (voir hts_add_file)
  2339.                      if (b) {
  2340.                      if ( ( ((int) b-(int) a) + strlen(codebase)) < HTS_URLMAXSIZE)
  2341.                      strncat(lien,a,(int) b-(int) a);    // nom du fichier
  2342.                      else {
  2343.                      if (opt.errlog) {   
  2344.                      fprintf(opt.errlog,"Error: Java-Parser generated link that exceeds %d bytes"LF,HTS_URLMAXSIZE);
  2345.                      test_flush;
  2346.                      }
  2347.                      }
  2348.                      } else a=NULL;
  2349.                      
  2350.                       if (strnotempty(lien)==0) a=NULL;  // fin
  2351.                       if (a)
  2352.                       a=b+1;
  2353.                     */
  2354.                     
  2355.                     if (strnotempty(lien)) {
  2356.                       
  2357.                       // calculer les chemins et noms de sauvegarde
  2358.                       if (ident_url_relatif(lien,urladr,codebase,adr,fil)>=0) { // reformage selon chemin
  2359.                         int r;
  2360.                         
  2361.                         //  patcher opt pour garder structure originale!! (on ne patche pas les noms dans la classe java!)
  2362.                         //##if (!strstr(lien,"://")) {         // PAS tester les http://.. inutile (on ne va pas patcher le binaire :-( )
  2363.                         if (1) {
  2364.                           char tempo[HTS_URLMAXSIZE*2];
  2365.                           int a,b;
  2366.                           tempo[0]='\0';
  2367.                           a=opt.savename_type;
  2368.                           b=opt.savename_83;
  2369.                           opt.savename_type=0;
  2370.                           opt.savename_83=0;
  2371.                           // note: adr,fil peuvent Ωtre patchΘs
  2372.                           r=url_savename(adr,fil,save,NULL,NULL,NULL,NULL,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe);
  2373.                           opt.savename_type=a;
  2374.                           opt.savename_83=b;
  2375.                           if (r != -1) {
  2376.                             if (savename) {
  2377.                               if (lienrelatif(tempo,save,savename)==0) {
  2378.                                 if ((opt.debug>1) && (opt.log!=NULL)) {
  2379.                                   fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): relative link at %s build with %s and %s: %s"LF,adr,save,savename,tempo);
  2380.                                   test_flush;
  2381.                                 }
  2382.                                 //
  2383.                                 // xxc xxc xxc xxc TODO java:
  2384.                                 // rebuild the java class with patched strings...
  2385.                                 //
  2386.                                 if (strlen(tempo)<=strlen(lien)) {
  2387.                                   FILE* fp=fopen(savename,"r+b");
  2388.                                   if (fp) {
  2389.                                     if (!fseek(fp,file_position,SEEK_SET)) {
  2390.                                       //unsigned short int string_length=strlen(tempo);
  2391.                                       //fwrite(&valint,sizeof(string_length),1,fp);
  2392.                                       // xxc xxc ARGH! SI la taille est <, dΘcaler le code ?!
  2393.                                     } else {
  2394.                                       if (opt.log!=NULL) {
  2395.                                         fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): unable to patch: %s"LF,savename);
  2396.                                         test_flush;
  2397.                                       }
  2398.                                     }
  2399.                                     fclose(fp);
  2400.                                   } else {
  2401.                                     if (opt.log!=NULL) {
  2402.                                       fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): unable to open: %s"LF,savename);
  2403.                                       test_flush;
  2404.                                     }
  2405.                                   }
  2406.                                 } else {
  2407.                                   if (opt.log!=NULL) {
  2408.                                     fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): link too long, unable to write it: %s"LF,tempo);
  2409.                                     test_flush;
  2410.                                   }
  2411.                                 }
  2412.                               }
  2413.                             }
  2414.                           }
  2415.                         } else {
  2416.                           if ((opt.debug>1) && (opt.log!=NULL)) {
  2417.                             fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): file not caught: %s"LF,lien); test_flush;
  2418.                           }
  2419.                           r=-1;
  2420.                         }
  2421.                         //
  2422.                         if (r != -1) {
  2423.                           if ((opt.debug>1) && (opt.log!=NULL)) {
  2424.                             fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): %s%s -> %s (base %s)"LF,adr,fil,save,codebase); test_flush;
  2425.                           }
  2426.                           
  2427.                           // modifiΘ par rapport α l'autre version (cf prio_fix notamment et save2)
  2428.                           
  2429.                           // vΘrifier que le lien n'a pas dΘja ΘtΘ notΘ
  2430.                           // si c'est le cas, alors il faut s'assurer que la prioritΘ associΘe
  2431.                           // au fichier est la plus grande des deux prioritΘs
  2432.                           //
  2433.                           // On part de la fin et on essaye de se presser (Θconomise temps machine)
  2434. #if HTS_HASH
  2435.                           {
  2436.                             int i=hash_read(&hash,save,"",0);      // lecture type 0 (sav)
  2437.                             if (i>=0) {
  2438.                               liens[i]->depth=maximum(liens[i]->depth,prio_fix);
  2439.                               dejafait=1;
  2440.                             }
  2441.                           }
  2442. #else
  2443.                           {
  2444.                             register int l;
  2445.                             register int i;
  2446.                             l=strlen(save);
  2447.                             for(i=lien_tot-1;(i>=0) && (dejafait==0);i--) {
  2448.                               if (liens[i]->sav_len==l) {    // mΩme taille de chaεne
  2449.                                 if (strcmp(liens[i]->sav,save)==0) {    // existe dΘja
  2450.                                   liens[i]->depth=maximum(liens[i]->depth,prio_fix);
  2451.                                   dejafait=1;
  2452.                                 }
  2453.                               }
  2454.                             }
  2455.                           }
  2456. #endif
  2457.                           
  2458.                           
  2459.                           if (!dejafait) {
  2460.                             //
  2461.                             // >>>> CREER LE LIEN JAVA <<<<
  2462.                             
  2463.                             // enregistrer fichier de java (MACRO)
  2464.                             liens_record(adr,fil,save,"","");
  2465.                             if (liens[lien_tot]==NULL) {  // erreur, pas de place rΘservΘe
  2466.                               printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  2467.                               if (opt.errlog) { 
  2468.                                 fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  2469.                                 test_flush;
  2470.                               }
  2471.                               // if ((opt.getmode & 1) && (ptr>0)) { if (fp) { fclose(fp); fp=NULL; } }
  2472.                               XH_extuninit;    // dΘsallocation mΘmoire & buffers
  2473.                               return 0;
  2474.                             }  
  2475.                             
  2476.                             // mode test?                          
  2477.                             liens[lien_tot]->testmode=0;          // pas mode test
  2478.                             
  2479.                             liens[lien_tot]->link_import=0;       // pas mode import
  2480.                             
  2481.                             // Θcrire autres paramΦtres de la structure-lien
  2482.                             //if (meme_adresse)                                 
  2483.                             liens[lien_tot]->premier=liens[ptr]->premier;
  2484.                             //else    // sinon l'objet pΦre est le prΘcΘdent lui mΩme
  2485.                             //  liens[lien_tot]->premier=ptr;
  2486.                             
  2487.                             liens[lien_tot]->precedent=ptr;
  2488.                             // noter la prioritΘ
  2489.                             liens[lien_tot]->depth=prio_fix;
  2490.                             liens[lien_tot]->pass2=max(pass_fix,numero_passe);
  2491.                             liens[lien_tot]->retry=opt.retry;
  2492.                             
  2493.                             //strcpy(liens[lien_tot]->adr,adr);
  2494.                             //strcpy(liens[lien_tot]->fil,fil);
  2495.                             //strcpy(liens[lien_tot]->sav,save); 
  2496.                             if ((opt.debug>1) && (opt.log!=NULL)) {
  2497.                               fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): OK, NOTE: %s%s -> %s"LF,liens[lien_tot]->adr,liens[lien_tot]->fil,liens[lien_tot]->sav);
  2498.                               test_flush;
  2499.                             }
  2500.                             
  2501.                             lien_tot++;  // UN LIEN DE PLUS
  2502.                           }
  2503.                         }      
  2504.                         }  
  2505.                         
  2506.                       }  
  2507.                     }
  2508.                     
  2509.                   }
  2510.                   //##// effacer buffer temporaire
  2511.                   //##if (buffer) freet(buffer); buffer=NULL;
  2512.                   //##}  // if buffer
  2513.               }  // if exist
  2514.             }  // if .class
  2515.           }  // if strlen-savename
  2516.         }  // if opt.parsejava
  2517.         
  2518.         
  2519.         
  2520.       }  // text/html ou autre
  2521.       
  2522.     }  // if !error
  2523.     
  2524.  
  2525. jump_if_done:
  2526.     // libΘrer les liens
  2527.     if (r.adr) { freet(r.adr); r.adr=NULL; }   // libΘrer la mΘmoire!
  2528.     
  2529.     // prochain lien
  2530.     ptr++;
  2531.     
  2532.     // faut-il sauter le(s) lien(s) suivant(s)? (fichiers images α passer aprΦs les html)
  2533.     if (opt.getmode & 4) {    // sauver les non html aprΦs
  2534.       // sauter les fichiers selon la passe
  2535.       if (!numero_passe) {
  2536.         while((ptr<lien_tot)?(   liens[ptr]->pass2):0) ptr++;
  2537.       } else {
  2538.         while((ptr<lien_tot)?( ! liens[ptr]->pass2):0) ptr++;
  2539.       }
  2540.       if (ptr>=lien_tot) {     // fin de boucle
  2541.         if (!numero_passe) { // premiΦre boucle
  2542.           if ((opt.debug>1) && (opt.log!=NULL)) {
  2543.             fprintf(opt.log,LF"Now getting non-html files..."LF);
  2544.             test_flush;
  2545.           }
  2546.           numero_passe=1;   // seconde boucle
  2547.           ptr=0;
  2548.           // prochain pass2
  2549.           while((ptr<lien_tot)?(!liens[ptr]->pass2):0) ptr++;
  2550.           
  2551.           //printf("first link==%d\n");
  2552.           
  2553.         }
  2554.       }  
  2555.     }
  2556.         
  2557.     // a-t-on dΘpassΘ le quota?
  2558.     if ((opt.maxsite>0) && (HTS_STAT.stat_bytes>=opt.maxsite)) {
  2559.       if (opt.errlog) {
  2560.         fprintf(opt.errlog,"More than %d bytes have been transfered.. giving up"LF,opt.maxsite);
  2561.         test_flush;
  2562.       } 
  2563.       ptr=lien_tot;
  2564.     } else if ((opt.maxtime>0) && ((time_local()-HTS_STAT.stat_timestart)>opt.maxtime)) {            
  2565.       if (opt.errlog) {
  2566.         fprintf(opt.errlog,"More than %d seconds passed.. giving up"LF,opt.maxtime);
  2567.         test_flush;
  2568.       } 
  2569.       ptr=lien_tot;
  2570.     } else if (exit_xh) {  // sortir
  2571.       if (opt.errlog) {
  2572.         fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  2573.         test_flush;
  2574.       } 
  2575.       ptr=lien_tot;
  2576.     }
  2577.   } while(ptr<lien_tot);
  2578.   //
  2579.   //
  2580.   //
  2581.  
  2582.  
  2583.   // no data transfered, no data saved
  2584.   // we assume that something was bad (no connection)
  2585.   // just backup old cache and restore everything
  2586.   if ( (HTS_STAT.stat_files == 0) && (new_stat_bytes < 2048) ) {
  2587.     if (opt.errlog) {
  2588.       fspc(opt.errlog,"info"); fprintf(opt.errlog,"No data seems to have been transfered during this session! : restoring previous one!"LF);
  2589.       test_flush;
  2590.     } 
  2591.     XH_uninit;
  2592.     if ( (fexist(fconcat(opt.path_log,"hts-cache/old.dat"))) && (fexist(fconcat(opt.path_log,"hts-cache/old.ndx"))) ) {
  2593.       remove(fconcat(opt.path_log,"hts-cache/new.dat"));
  2594.       remove(fconcat(opt.path_log,"hts-cache/new.ndx"));
  2595.       remove(fconcat(opt.path_log,"hts-cache/new.lst"));
  2596.       rename(fconcat(opt.path_log,"hts-cache/old.dat"),fconcat(opt.path_log,"hts-cache/new.dat"));
  2597.       rename(fconcat(opt.path_log,"hts-cache/old.ndx"),fconcat(opt.path_log,"hts-cache/new.ndx"));
  2598.       rename(fconcat(opt.path_log,"hts-cache/old.lst"),fconcat(opt.path_log,"hts-cache/new.lst"));
  2599.     }
  2600.     exit_xh=2;        /* interrupted (no connection detected) */
  2601.     return 1;
  2602.   }
  2603.  
  2604.  
  2605.   // purger!
  2606.   if (opt.delete_old) {
  2607.     if (cache.lst) {
  2608.       FILE *old_lst,*new_lst;
  2609.       //
  2610. #if HTS_ANALYSTE==2
  2611.       _hts_in_html_parsing=3;
  2612. #endif
  2613.       //
  2614.       fclose(cache.lst); cache.lst=NULL;
  2615.       old_lst=fopen(fconcat(opt.path_log,"hts-cache/old.lst"),"rb");
  2616.       if (old_lst) {
  2617.         LLint sz=fsize(fconcat(opt.path_log,"hts-cache/new.lst"));
  2618.         new_lst=fopen(fconcat(opt.path_log,"hts-cache/new.lst"),"rb");
  2619.         if ((new_lst) && (sz>0)) {
  2620.           char* adr=(char*) malloct((INTsys)sz);
  2621.           if (adr) {
  2622.             if ((int) fread(adr,1,(INTsys)sz,new_lst) == sz) {
  2623.               char line[1100];
  2624.               int purge=0;
  2625.               while(!feof(old_lst)) {
  2626.                 linput(old_lst,line,1000);
  2627.                 if (!strstr(adr,line)) {    // fichier non trouvΘ dans le nouveau?
  2628.                   char file[HTS_URLMAXSIZE*2];
  2629.                   strcpy(file,opt.path_html);
  2630.                   strcat(file,line+1);
  2631.                   file[strlen(file)-1]='\0';
  2632.                   if (fexist(file)) {       // toujours sur disque: virer
  2633.                     if (opt.log) {
  2634.                       fspc(opt.log,"info"); fprintf(opt.log,"Purging %s"LF,file);
  2635.                     }
  2636.                     remove(file); purge=1;
  2637.                   }
  2638.                 }
  2639.               }
  2640.               {
  2641.                 fseek(old_lst,0,SEEK_SET);
  2642.                 while(!feof(old_lst)) {
  2643.                   linput(old_lst,line,1000);
  2644.                   while(strnotempty(line) && (line[strlen(line)-1]!='/') && (line[strlen(line)-1]!='\\')) {
  2645.                     line[strlen(line)-1]='\0';
  2646.                   }
  2647.                   if (strnotempty(line))
  2648.                     line[strlen(line)-1]='\0';
  2649.                   if (strnotempty(line))
  2650.                     if (!strstr(adr,line)) {    // non trouvΘ?
  2651.                       char file[HTS_URLMAXSIZE*2];
  2652.                       strcpy(file,opt.path_html);
  2653.                       strcat(file,line+1);
  2654.                       while ((strnotempty(file)) && (rmdir(file)==0)) {    // ok, ΘliminΘ (existait)
  2655.                         purge=1;
  2656.                         if (opt.log) {
  2657.                           fspc(opt.log,"info"); fprintf(opt.log,"Purging directory %s/"LF,file);
  2658.                           while(strnotempty(file) && (file[strlen(file)-1]!='/') && (file[strlen(file)-1]!='\\')) {
  2659.                             file[strlen(file)-1]='\0';
  2660.                           }
  2661.                           if (strnotempty(file))
  2662.                             file[strlen(file)-1]='\0';
  2663.                         }
  2664.                       }
  2665.                     }
  2666.                 }
  2667.               }
  2668.               //
  2669.               if (!purge) {
  2670.                 if (opt.log) {
  2671.                   fprintf(opt.log,"No files purged"LF);
  2672.                 }
  2673.               }
  2674.             }
  2675.             freet(adr);
  2676.           }
  2677.           fclose(new_lst);
  2678.         }
  2679.         fclose(old_lst);
  2680.       }
  2681.       //
  2682. #if HTS_ANALYSTE==2
  2683.       _hts_in_html_parsing=0;
  2684. #endif
  2685.     }
  2686.   }
  2687.   // fin purge!
  2688.   
  2689.  
  2690.   // Indexation
  2691.   if (opt.kindex)
  2692.     index_finish(opt.path_html);
  2693.  
  2694.   // afficher rΘsumΘ dans log
  2695.   if (opt.log!=NULL) {
  2696.     int error   = fspc(NULL,"error");
  2697.     int warning = fspc(NULL,"warning");
  2698.     int info    = fspc(NULL,"info");
  2699.     char htstime[256];
  2700.     // int n=(int) (stat_loaded/(time_local()-HTS_STAT.stat_timestart));
  2701.     int n=(int) (new_stat_bytes/(time_local()-HTS_STAT.stat_timestart));
  2702.     sec2str(htstime,time_local()-HTS_STAT.stat_timestart);
  2703.     //fprintf(opt.log,LF"HTS-mirror complete in %s : %d links scanned, %d files written (%d bytes overall) [%d bytes received at %d bytes/sec]"LF,htstime,lien_tot-1,HTS_STAT.stat_files,stat_bytes,stat_loaded,n);
  2704.     fprintf(opt.log,LF"HTTrack mirror complete in %s : %d links scanned, %d files written (%d bytes overall) [%d bytes received at %d bytes/sec]"LF,htstime,(int)lien_tot-1,(int)HTS_STAT.stat_files,(int)HTS_STAT.stat_bytes,(int)new_stat_bytes,(int)n);
  2705.     if (error)
  2706.       fprintf(opt.log,"(%d errors, %d warnings, %d messages)"LF,error,warning,info);
  2707.     else
  2708.       fprintf(opt.log,"(No errors, %d warnings, %d messages)"LF,warning,info);
  2709.     test_flush;
  2710.   }
  2711. #if DEBUG_HASH
  2712.   // noter les collisions
  2713.   {
  2714.     int i;
  2715.     int empty1=0,empty2=0,empty3=0;
  2716.     for(i=0;i<HTS_HASH_SIZE;i++) {
  2717.       if (hash.hash[0][i] == -1)
  2718.         empty1++;
  2719.       if (hash.hash[1][i] == -1)
  2720.         empty2++;
  2721.       if (hash.hash[2][i] == -1)
  2722.         empty3++;
  2723.     }
  2724.     printf("\n");
  2725.     printf("Debug info: Hash-table report\n");
  2726.     printf("Number of files entered:   %d\n",hashnumber);
  2727.     printf("Table size:                %d\n",HTS_HASH_SIZE);
  2728.     printf("\n");
  2729.     printf("Longest chain sav:              %d, empty: %d\n",longest_hash[0],empty1);
  2730.     printf("Longest chain adr,fil:          %d, empty: %d\n",longest_hash[1],empty2);
  2731.     printf("Longest chain former_adr/fil:   %d, empty: %d\n",longest_hash[2],empty3);
  2732.     printf("\n");
  2733.   }
  2734. #endif    
  2735.   // fin afficher rΘsumΘ dans log
  2736.   
  2737.   // dΘsallocation mΘmoire & buffers  
  2738.   XH_uninit    
  2739.  
  2740.   return 1;    // OK
  2741. }
  2742. // version 2 pour le reste
  2743. // flusher si on doit lire peu α peu le fichier
  2744. #undef test_flush
  2745. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  2746.  
  2747.  
  2748. // Estimate transfer rate
  2749. int engine_stats() {
  2750.   if ( ((mtime_local() - HTS_STAT.imstat_timestart) >= 2000) && (new_stat_bytes>2048) ) {
  2751.     double cdif;
  2752.     double dif;
  2753.     cdif=mtime_local();
  2754.     dif=cdif - HTS_STAT.imstat_timestart;
  2755.     if (dif) {
  2756.       LLint byt=(int) (new_stat_bytes-HTS_STAT.istat_bytes);
  2757.       HTS_STAT.rate=(LLint)((double) ((double)byt/(dif/1000.0)));
  2758.       //
  2759.       HTS_STAT.istat_bytes=new_stat_bytes;
  2760.       HTS_STAT.imstat_timestart=cdif;
  2761.     }
  2762.     return 1;       /* refreshed */
  2763.   }
  2764.   return 0;
  2765. }
  2766.  
  2767.  
  2768. // bannir host (trop lent etc)
  2769. void host_ban(httrackp* opt,lien_url** liens,int ptr,int lien_tot,lien_back* back,int back_max,char** filters,int filter_max,int* filptr,char* host) {
  2770.   //register int l;
  2771.   register int i;
  2772.  
  2773.   if (host[0]=='!')
  2774.     return;    // erreur.. dΘja cancellΘ.. bizzard.. devrait pas arriver
  2775.  
  2776.   // interdire host
  2777.   if (*filptr < filter_max) {
  2778.     strcpy(filters[*filptr],"-");
  2779.     strcat(filters[*filptr],host);
  2780.     strcat(filters[*filptr],"/*");     // host/ * interdit
  2781.     (*filptr)++; *filptr=minimum(*filptr,filter_max);  
  2782.   }
  2783.   
  2784.   // oups
  2785.   if (strlen(host)<=1) {    // euhh?? longueur <= 1
  2786.     if (strcmp(host,"file://")) {
  2787.       //## if (host[0]!=lOCAL_CHAR) {  // pas local
  2788.       if (opt->log!=NULL) {
  2789.         fprintf(opt->log,"PANIC! HostCancel detected memory leaks [char %d]"LF,host[0]); test_flush;
  2790.       }          
  2791.       return;  // purΘe
  2792.     }
  2793.   }
  2794.   
  2795.   // couper connexion
  2796.   for(i=0;i<back_max;i++) {
  2797.     if (back[i].status>=0)    // rΘception OU prΩt
  2798.       if (strfield2(back[i].url_adr,host)) {
  2799. #if HTS_DEBUG_CLOSESOCK
  2800.         DEBUG_W("host control: deletehttp\n");
  2801. #endif
  2802.         back[i].status=0;  // terminΘ
  2803.         if (back[i].r.soc!=INVALID_SOCKET) deletehttp(&back[i].r);
  2804.         back[i].r.soc=INVALID_SOCKET;
  2805.         back[i].r.statuscode=-2;    // timeout (peu importe si c'est un traffic jam)
  2806.         strcpy(back[i].r.msg,"Link Cancelled by host control");
  2807.         
  2808.         if ((opt->debug>1) && (opt->log!=NULL)) {
  2809.           fprintf(opt->log,"Shutdown: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  2810.         }          
  2811.       }
  2812.   }
  2813.   
  2814.   // effacer liens
  2815.   //l=strlen(host);
  2816.   for(i=0;i<lien_tot;i++) {
  2817.     //if (liens[i]->adr_len==l) {    // mΩme taille de chaεne
  2818.     // Calcul de taille sΘcurisΘe
  2819.     if (liens[i]) {
  2820.       if (liens[i]->adr) {
  2821.         int l = 0;
  2822.         while((liens[i]->adr[l]) && (l<1020)) l++;
  2823.         if ((l > 0) && (l<1020)) {   // sΘcuritΘ
  2824.           if (strfield2(jump_identification(liens[i]->adr),host)) {    // host
  2825.             if ((opt->debug>1) && (opt->log!=NULL)) {
  2826.               fprintf(opt->log,"Cancel: %s%s"LF,liens[i]->adr,liens[i]->fil); test_flush;
  2827.             }
  2828.             strcpy(liens[i]->adr,"!");    // cancel (invalide hash)
  2829. #if HTS_HASH
  2830. #else
  2831.             liens[i]->sav_len=-1;         // taille invalide
  2832. #endif
  2833.             // on efface pas le hash, because si on rencontre le lien, reverif sav..
  2834.           }
  2835.         } else {
  2836.           if (opt->log!=NULL) {
  2837.             char dmp[1040];
  2838.             dmp[0]='\0';
  2839.             strncat(dmp,liens[i]->adr,1024);
  2840.             fprintf(opt->log,"WARNING! HostCancel detected memory leaks [len %d at %d]"LF,l,i); test_flush;
  2841.             fprintf(opt->log,"dump 1024 bytes (address %d): "LF"%s"LF,(int)liens[i]->adr,dmp); test_flush;
  2842.           }          
  2843.         }
  2844.       } else {
  2845.         if (opt->log!=NULL) {
  2846.           fprintf(opt->log,"WARNING! HostCancel detected memory leaks [adr at %d]"LF,i); test_flush;
  2847.         }  
  2848.       }
  2849.     } else {
  2850.       if (opt->log!=NULL) {
  2851.         fprintf(opt->log,"WARNING! HostCancel detected memory leaks [null at %d]"LF,i); test_flush;
  2852.       }  
  2853.     }
  2854.     //}
  2855.   }
  2856. }
  2857.  
  2858.  
  2859.  
  2860.  
  2861.  
  2862.  
  2863. // vΘrifier prΘsence de l'arbo
  2864. int structcheck(char* s) {
  2865.   // vΘrifier la prΘsence des dossier(s)
  2866.   char *a=s;
  2867.   char nom[HTS_URLMAXSIZE*2];
  2868.   char *b;
  2869.  
  2870.   if (strnotempty(s)==0) return 0;
  2871.   if (strlen(s)>HTS_URLMAXSIZE) return 0;
  2872.  
  2873.   if (structcheck_buff==NULL) {
  2874.     structcheck_buff=(char*) malloct(65536);  // ** ** non dΘsallouΘ
  2875.     strcpy(structcheck_buff,"#");
  2876.   } else if (strlen(structcheck_buff)>65000) {
  2877.     strcpy(structcheck_buff,"#");  // rΘinit.. c'est idiot ** **
  2878.   }
  2879.   
  2880.   if (structcheck_buff) {
  2881.     b=nom;
  2882.     do {    
  2883.       if (*a) *b++=*a++;
  2884.       while((*a!='/') && (*a!='\0')) *b++=*a++;
  2885.       *b='\0';    // pas de ++ pour boucler
  2886.       if (*a=='/') {    // toujours dossier
  2887.         if (strnotempty(nom)) {
  2888.           char tempo[HTS_URLMAXSIZE*2];
  2889.           
  2890.           strcpy(tempo,"#"); strcat(tempo,nom); strcat(tempo,"#");
  2891.           if (strstr(structcheck_buff,tempo)==NULL) {    // non encore crΘΘ
  2892.             strcat(structcheck_buff,"#"); strcat(structcheck_buff,nom); strcat(structcheck_buff,"#");  // ajouter α la liste
  2893.                         
  2894. #if HTS_WIN
  2895.             if (mkdir(fconv(nom))!=0)
  2896. #else    
  2897.               if (mkdir(fconv(nom),HTS_ACCESS_FOLDER)!=0)
  2898. #endif
  2899.               {
  2900. #if HTS_REMOVE_ANNOYING_INDEX
  2901.                 // might be a filename with same name than this folder
  2902.                 // then, remove it to allow folder creation
  2903.                 // it happends when servers gives a folder index while
  2904.                 // requesting / page
  2905.                 // -> if the file can be opened (not a folder) then rename it
  2906.                 FILE* fp=fopen(fconv(nom),"ab");
  2907.                 if (fp) {
  2908.                   fclose(fp);
  2909.                   rename(fconv(nom),fconcat(fconv(nom),".txt"));
  2910.                 }
  2911.                 // if it fails, that's too bad
  2912. #if HTS_WIN
  2913.                 mkdir(fconv(nom));
  2914. #else    
  2915.                 mkdir(fconv(nom),HTS_ACCESS_FOLDER);
  2916. #endif
  2917. #endif
  2918.                 // Si existe dΘja renvoie une erreur.. tant pis
  2919.               }
  2920. #if HTS_WIN==0
  2921.               chmod(fconv(nom),HTS_ACCESS_FOLDER);
  2922. #endif
  2923.           }
  2924.         }
  2925.         *b++=*a++;    // slash
  2926.       } 
  2927.     } while(*a);
  2928.   }
  2929.   return 0;
  2930. }
  2931.  
  2932.  
  2933. // sauver un fichier
  2934. int filesave(char* adr,int len,char* s) {
  2935.   FILE* fp;
  2936.   // Θcrire le fichier
  2937.   if ((fp=filecreate(s))!=NULL) {
  2938.     int nl=0;
  2939.     if (len>0) {
  2940.       nl=(int) fwrite(adr,1,len,fp);
  2941.     }
  2942.     fclose(fp);
  2943.     usercommand(0,NULL,antislash(s));
  2944.     if (nl!=len)  // erreur
  2945.       return -1;
  2946.   } else
  2947.     return -1;
  2948.   
  2949.   return 0;
  2950. }
  2951.  
  2952.  
  2953. // ouvrir un fichier (avec chemin Un*x)
  2954. FILE* filecreate(char* s) {
  2955.   char fname[HTS_URLMAXSIZE*2];
  2956.   FILE* fp;
  2957.   fname[0]='\0';
  2958.  
  2959.   // noter lst
  2960.   filenote(s,NULL);
  2961.   
  2962.   // if (*s=='/') strcpy(fname,s+1); else strcpy(fname,s);    // pas de / (root!!) // ** SIIIIIII!!! α cause de -O <path>
  2963.   strcpy(fname,s);
  2964.  
  2965. #if HTS_DOSNAME
  2966.   // remplacer / par des slash arriΦre
  2967.   {
  2968.     int i=0;
  2969.     while(fname[i]) {
  2970.       if (fname[i]=='/')
  2971.         fname[i]='\\';
  2972.       i++;
  2973.     } 
  2974.   } 
  2975.   // a partir d'ici le slash devient antislash
  2976. #endif
  2977.   
  2978.   // construite le chemin si besoin est
  2979.   if (structcheck(s)!=0) {
  2980.     return NULL;
  2981.   }
  2982.   
  2983.   
  2984.   // ouvrir
  2985.   fp=fopen(fname,"wb");
  2986. #if HTS_WIN==0
  2987.   if (fp!=NULL) chmod(fname,HTS_ACCESS_FILE);
  2988. #endif
  2989.   return fp;
  2990. }
  2991.  
  2992. // noter fichier
  2993. int filenote(char* s,filecreate_params* params) {
  2994. //int filenote(char* s,char* params) {
  2995.   static FILE* lst = NULL;
  2996.   static char path[HTS_URLMAXSIZE*2]="";
  2997.   
  2998.   // gestion du fichier liste liste
  2999.   if (params) {
  3000.     //filecreate_params* p = (filecreate_params*) params;
  3001.     strcpy(path,params->path);
  3002.     lst=params->lst;
  3003.     return 0;
  3004.   } else if (lst) {
  3005.     char savelst[HTS_URLMAXSIZE*2];
  3006.     strcpy(savelst,fslash(s));
  3007.     // couper chemin?
  3008.     if (strnotempty(path)) {
  3009.       if (strncmp(fslash(path),savelst,strlen(path))==0) {  // couper
  3010.         strcpy(savelst,s+strlen(path));
  3011.       }
  3012.     }
  3013.     fprintf(lst,"[%s]"LF,savelst);
  3014.     fflush(lst);
  3015.   }
  3016.   return 1;
  3017. }
  3018.  
  3019. // executer commande utilisateur
  3020. HTS_INLINE void usercommand(int _exe,char* _cmd,char* file) {
  3021.   static int exe=0;
  3022.   static char cmd[2048]="";
  3023.   if (_exe) {
  3024.     strcpy(cmd,_cmd);
  3025.     if (strnotempty(cmd))
  3026.       exe=_exe;
  3027.     else
  3028.       exe=0;
  3029.   }
  3030.   if (exe) {
  3031.     if (strnotempty(file)) {
  3032.       if (strnotempty(cmd)) {
  3033.         usercommand_exe(cmd,file);
  3034.       }
  3035.     }
  3036.   }
  3037. }
  3038. void usercommand_exe(char* cmd,char* file) {
  3039.   char temp[8192];
  3040.   char c[2]="";
  3041.   int i;
  3042.   temp[0]='\0';
  3043.   //
  3044.   for(i=0;i<(int) strlen(cmd);i++) {
  3045.     if ((cmd[i]=='$') && (cmd[i+1]=='0')) {
  3046.       strcat(temp,file);
  3047.       i++;
  3048.     } else {
  3049.       c[0]=cmd[i]; c[1]='\0';
  3050.       strcat(temp,c);
  3051.     }
  3052.   }
  3053.   system(temp);
  3054. }
  3055.  
  3056. // Θcrire n espaces dans fp
  3057. HTS_INLINE int fspc(FILE* fp,char* type) {
  3058.   static int error=0,warning=0,info=0;
  3059.   //
  3060.   if (fp) {
  3061.     char s[256];
  3062.     time_t tt;
  3063.     struct tm* A;
  3064.     tt=time(NULL);
  3065.     A=localtime(&tt);
  3066.     strftime(s,250,"%H:%M:%S",A);
  3067.     if (strnotempty(type))
  3068.       fprintf(fp,"%s\t%c%s: \t",s,hichar(*type),type+1);
  3069.     else
  3070.       fprintf(fp,"%s\t \t",s);
  3071.     if (strcmp(type,"warning")==0)
  3072.       warning++;
  3073.     else if (strcmp(type,"error")==0)
  3074.       error++;
  3075.     else if (strcmp(type,"info")==0)
  3076.       info++;
  3077.   } 
  3078.   else if (strcmp(type,"warning")==0)
  3079.     return warning;
  3080.   else if (strcmp(type,"error")==0)
  3081.     return error;
  3082.   else if (strcmp(type,"info")==0)
  3083.     return info;
  3084.   return 0;
  3085. }
  3086.  
  3087.  
  3088. // vΘrifier taux de transfert
  3089. void check_rate(double stat_timestart,int maxrate) {
  3090.   // vΘrifier taux de transfert (pas trop grand?)
  3091.   if (maxrate>0) {
  3092.     int r = (int) (new_stat_bytes/(time_local()-stat_timestart));    // taux actuel de transfert
  3093.     HTS_STAT.HTS_TOTAL_RECV_STATE=0;
  3094.     if (r>maxrate) {    // taux>taux autorisΘ
  3095.       int taux = (int) (((double) (r - maxrate) * 100) / (double) maxrate);
  3096.       if (taux<15)
  3097.         HTS_STAT.HTS_TOTAL_RECV_STATE=1;   // ralentir un peu (<15% dΘpassement)
  3098.       else if (taux<50)
  3099.         HTS_STAT.HTS_TOTAL_RECV_STATE=2;   // beaucoup (<50% dΘpassement)
  3100.       else
  3101.         HTS_STAT.HTS_TOTAL_RECV_STATE=3;   // ΘnormΘment (>50% dΘpassement)
  3102.     }
  3103.   }
  3104. }
  3105.  
  3106.  
  3107. // ---
  3108. // sous routines liΘes au moteur et au backing
  3109.  
  3110. // supplemental links ready (done) after ptr
  3111. int backlinks_done(lien_url** liens,int lien_tot,int ptr) {
  3112.   int n=0;
  3113.   int i;
  3114.   //Links done and stored in cache
  3115.   for(i=ptr+1;i<lien_tot;i++) {
  3116.     if (liens[i]) {
  3117.       if (liens[i]->pass2 == -1) {
  3118.         n++;
  3119.       }
  3120.     }
  3121.   }
  3122.   return n;
  3123. }
  3124.  
  3125. // remplir backing si moins de max_bytes en mΘmoire
  3126. HTS_INLINE int back_fillmax(lien_back* back,int back_max,httrackp* opt,cache_back* cache,lien_url** liens,int ptr,int numero_passe,int lien_tot) {
  3127.   if (back_incache(back,back_max)<opt->maxcache) {  // pas trop en mΘmoire?
  3128.     return back_fill(back,back_max,opt,cache,liens,ptr,numero_passe,lien_tot);
  3129.   }
  3130.   return -1;                /* plus de place */
  3131. }
  3132.  
  3133. // remplir backing
  3134. int back_fill(lien_back* back,int back_max,httrackp* opt,cache_back* cache,lien_url** liens,int ptr,int numero_passe,int lien_tot) {
  3135.   int n;
  3136.  
  3137.   // ajouter autant de socket qu'on peut ajouter
  3138.   n=opt->maxsoc-back_nsoc(back,back_max);
  3139.  
  3140.   // vΘrifier qu'il restera assez de place pour les tests ensuite (en thΘorie, 1 entrΘe libre restante suffirait)
  3141.   n=min( n, back_available(back,back_max) - 8 );
  3142.  
  3143.   // no space left on backing stack - do not back anymore
  3144.   if (back_stack_available(back,back_max) <= 2)
  3145.     n=0;
  3146.  
  3147.   if (n>0) {
  3148.     int p;
  3149.  
  3150.     if (ptr<cache->ptr_last) {      /* restart (2 scans: first html, then non html) */
  3151.       cache->ptr_ant=0;
  3152.     }
  3153.  
  3154.     p=ptr+1;
  3155.     /* on a dΘja parcouru */
  3156.     if (p<cache->ptr_ant)
  3157.       p=cache->ptr_ant;
  3158.     while( (p<lien_tot) && (n>0) ) {
  3159.     //while((p<lien_tot) && (n>0) && (p < ptr+opt->maxcache_anticipate)) {
  3160.       int ok=1;
  3161.       
  3162.       // on ne met pas le fichier en backing si il doit Ωtre traitΘ aprΦs
  3163.       if (liens[p]->pass2) {  // 2Φ passe
  3164.         if (numero_passe!=1)
  3165.           ok=0;
  3166.       } else {
  3167.         if (numero_passe!=0)
  3168.           ok=0;
  3169.       }
  3170.       
  3171.       // note: si un backing est fini, il reste en mΘmoire jusqu'α ce que
  3172.       // le ptr l'atteigne
  3173.       if (ok) {
  3174.         if (!back_exist(back,back_max,liens[p]->adr,liens[p]->fil,liens[p]->sav)) {
  3175.           if (back_add(back,back_max,opt,cache,liens[p]->adr,liens[p]->fil,liens[p]->sav,liens[liens[p]->precedent]->adr,liens[liens[p]->precedent]->fil,liens[p]->testmode,&liens[p]->pass2)==-1) {
  3176.             if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  3177.               fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: unable to add more links through back_add for back_fill"LF);
  3178.               test_flush;
  3179.             }                    
  3180. #if BDEBUG==1
  3181.             printf("error while adding\n");
  3182. #endif                  
  3183.             n=0;    // sortir
  3184.           } else {
  3185.             n--;
  3186. #if BDEBUG==1
  3187.             printf("backing: %s%s\n",liens[p]->adr,liens[p]->fil);          
  3188. #endif
  3189.           } 
  3190.         }
  3191.       }
  3192.       p++;
  3193.     }  // while
  3194.     /* sauver position derniΦre anticipation */
  3195.     cache->ptr_ant=p;
  3196.     cache->ptr_last=ptr;
  3197.   }
  3198.   return 0;
  3199. }
  3200. // ---
  3201.  
  3202.  
  3203.  
  3204.  
  3205.  
  3206.  
  3207.  
  3208.  
  3209.  
  3210.  
  3211.  
  3212.  
  3213.  
  3214.  
  3215.  
  3216.  
  3217.  
  3218.  
  3219. // routines de dΘtournement de SIGHUP & co (Unix)
  3220. void sig_finish( int code ) {       // finir et quitter
  3221.   signal(code,sig_term);  // quitter si encore
  3222.   exit_xh=1;
  3223.   printf("\nExit requested to engine (signal %d)\n",code);
  3224. }
  3225. void sig_term( int code ) {       // quitter brutalement
  3226.   printf("\nProgram terminated (signal %d)\n",code);
  3227.   exit(0);
  3228. }
  3229. #if HTS_WIN
  3230. void sig_ask( int code ) {        // demander
  3231.   static char s[256];
  3232.   signal(code,sig_term);  // quitter si encore
  3233.   printf("\nQuit program/Cancel? (Q/C) ");
  3234.   fflush(stdout);
  3235.   scanf("%s",s);
  3236.   if ( (s[0]=='y') || (s[0]=='Y') || (s[0]=='o') || (s[0]=='O') || (s[0]=='q') || (s[0]=='Q'))
  3237.     exit(0);     // quitter
  3238.   signal(code,sig_ask);  // remettre signal
  3239. }
  3240. #else
  3241. void sig_back( int code ) {       // ignorer et mettre en backing 
  3242.   signal(code,sig_ignore);
  3243.   sig_doback(0);
  3244. }
  3245. void sig_ask( int code ) {        // demander
  3246.   static char s[256];
  3247.   signal(code,sig_term);  // quitter si encore
  3248.   printf("\nQuit program/Background/bLind background/Cancel? (Q/B/L/C) ");
  3249.   fflush(stdout);
  3250.   scanf("%s",s);
  3251.   if ( (s[0]=='y') || (s[0]=='Y') || (s[0]=='o') || (s[0]=='O') || (s[0]=='q') || (s[0]=='Q'))
  3252.     exit(0);     // quitter
  3253.   else if ( (s[0]=='b') || (s[0]=='B') || (s[0]=='a') || (s[0]=='A') )
  3254.     sig_doback(0);  // arriΦre plan
  3255.   else if ( (s[0]=='l') || (s[0]=='L') )
  3256.     sig_doback(1);  // arriΦre plan
  3257.   else {
  3258.     printf("cancel..\n");
  3259.     signal(code,sig_ask);  // remettre signal
  3260.   }
  3261. }
  3262. void sig_ignore( int code ) {     // ignorer signal
  3263.   // // signal(code,sig_ignore);
  3264. }
  3265. void sig_doback(int blind) {       // mettre en backing 
  3266.   int out=-1;
  3267.   //
  3268.   printf("\nMoving to background to complete the mirror...\n"); fflush(stdout);
  3269.   if (!blind)
  3270.     out = open("hts-nohup.out",O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR);
  3271.   if (out == -1)
  3272.     out = open("/dev/null",O_WRONLY,S_IRUSR|S_IWUSR);
  3273.   close(0);
  3274.   close(1);
  3275.   dup(out);
  3276.   close(2);
  3277.   dup(out);
  3278.   //
  3279.   switch (fork()) {
  3280.   case 0: 
  3281.     break;
  3282.   case -1:
  3283.     printf("Error: can not fork process\n");
  3284.     break;
  3285.   default:            // pere
  3286.     usleep(100000);   // pause 1/10s "A  microsecond  is  .000001s"
  3287.     _exit(0);
  3288.     break;  
  3289.   }
  3290. }
  3291. #endif
  3292. // fin routines de dΘtournement de SIGHUP & co
  3293.  
  3294. // Poll stdin.. si besoin
  3295. #if HTS_POLL
  3296. // lecture stdin des caractΦres disponibles
  3297. int read_stdin(char* s,int max) {
  3298.   int i=0;
  3299.   while((check_stdin()) && (i<(max-1)) )
  3300.     s[i++]=fgetc(stdin);
  3301.   s[i]='\0';
  3302.   return i;
  3303. }
  3304. #ifdef _WIN32
  3305. HTS_INLINE int check_stdin() {
  3306.   return (_kbhit());
  3307. }
  3308. #else
  3309. HTS_INLINE int check_flot(T_SOC s) {
  3310.   fd_set fds;
  3311.   struct timeval tv;
  3312.   FD_ZERO(&fds);
  3313.   FD_SET((T_SOC) s,&fds);
  3314.   tv.tv_sec=0;
  3315.   tv.tv_usec=0;
  3316.   select(s+1,&fds,NULL,NULL,&tv);
  3317.   return FD_ISSET(s,&fds);
  3318. }
  3319. HTS_INLINE int check_stdin() {
  3320.   fflush(stdout); fflush(stdin);
  3321.   if (check_flot(0))
  3322.     return 1;
  3323.   return 0;
  3324. }
  3325. #endif
  3326. #endif
  3327.  
  3328.  
  3329. // Attente de touche
  3330. #if HTS_ANALYSTE!=2
  3331. int ask_continue() {
  3332.   char s[12]="";
  3333.   printf("Press <Y><Enter> to confirm, <N><Enter> to abort\n");
  3334.   io_flush; linput(stdin,s,4);
  3335.   if (strnotempty(s)) {
  3336.     if ((strfield2(s,"N")) || (strfield2(s,"NO")) || (strfield2(s,"NON")))
  3337.       return 0;
  3338.   }
  3339.   return 1;
  3340. }
  3341. #else
  3342. int ask_continue() {
  3343.   char* s;
  3344.   s=hts_htmlcheck_query2(HTbuff);
  3345.   if (s) {
  3346.     if (strnotempty(s)) {
  3347.       if ((strfield2(s,"N")) || (strfield2(s,"NO")) || (strfield2(s,"NON")))
  3348.         return 0;
  3349.     }
  3350.     return 1;
  3351.   }
  3352.   return 1;
  3353. }
  3354. #endif
  3355.  
  3356. // nombre de digits dans un nombre
  3357. int nombre_digit(int n) {
  3358.   register int i=1;
  3359.   while(n >= 10) { n/=10; i++; }
  3360.   return i;
  3361. }
  3362.  
  3363.  
  3364. // renvoi adresse de la fin du token dans p
  3365. // renvoi NULL si la chaine est un token unique
  3366. // (PATCHE Θgalement la chaine)
  3367. // ex: "test" "test2" renvoi adresse sur espace
  3368. // flag==1 si chaine comporte des echappements comme \"
  3369. char* next_token(char* p,int flag) {
  3370.   int detect=0;
  3371.   int quote=0;
  3372.   p--;
  3373.   do {
  3374.     p++;
  3375.     if (flag && (*p=='\\')) {   // sauter \x ou \"
  3376.       if (quote) {
  3377.         char c='\0';
  3378.         if (*(p+1)=='\\')
  3379.           c='\\';
  3380.         else if (*(p+1)=='"')
  3381.           c='"';
  3382.         if (c) {
  3383.           char tempo[8192];
  3384.           tempo[0]=c; tempo[1]='\0';
  3385.           strcat(tempo,p+2);
  3386.           strcpy(p,tempo);
  3387.         }
  3388.       }
  3389.     }
  3390.     else if (*p==34) {  // guillemets (de fin)
  3391.       quote=!quote;
  3392.     }
  3393.     else if (*p==32) {
  3394.       if (!quote)
  3395.         detect=1;
  3396.     }
  3397.     else if (*p=='\0') {
  3398.       p=NULL;
  3399.       detect=1;
  3400.     }
  3401.   } while(!detect);
  3402.   return p;
  3403. }
  3404.  
  3405. // routines annexes 
  3406. #if HTS_ANALYSTE==2
  3407. // canceller un fichier (noter comme cancellable)
  3408. char* hts_cancel_file(char * s) {
  3409.   static char sav[HTS_URLMAXSIZE*2]="";
  3410.   if (s[0]!='\0')
  3411.   if (sav[0]=='\0')
  3412.     strcpy(sav,s);
  3413.   return sav;
  3414. }
  3415. void hts_cancel_test() {
  3416.   if (_hts_in_html_parsing==2)
  3417.     _hts_cancel=2;
  3418. }
  3419. void hts_cancel_parsing() {
  3420.   if (_hts_in_html_parsing)
  3421.    _hts_cancel=1;
  3422. }
  3423. #endif
  3424. //        for(_i=0;(_i<back_max) && (index<NFICH);_i++) {
  3425. //          i=(back_index+_i)%back_max;    // commencer par le "premier" (l'actuel)
  3426. //          if (back[i].status>=0) {     // signifie "lien actif"
  3427.  
  3428.  
  3429. /*  
  3430. hts_add_file, add/get elements in the add chain for java parsing
  3431. if file_position >= 0
  3432.   push 'file/file_position'
  3433.   return 1 (return 0 if exists)
  3434. else
  3435.   pop file -> 'file'
  3436.   return 'file_position'
  3437. else if empty/error
  3438.   return -1;
  3439. */
  3440. typedef struct addfile_chain {
  3441.   char name[1024];
  3442.   int pos;
  3443.   struct addfile_chain* next;
  3444. } addfile_chain;
  3445. int hts_add_file(char* file,int file_position) {
  3446.   static struct addfile_chain* chain=NULL;
  3447.  
  3448.   if (file_position>=0) {         /* copy file to the chain */
  3449.     struct addfile_chain** current;
  3450.     current=&chain;                     /* start from */
  3451.     while(*current) {
  3452.       if (strcmp((*current)->name,file)==0)
  3453.         return 0;                       /* already exists */
  3454.       current=&( (*current)->next );    /* 'next' address */
  3455.     }
  3456.     *current=calloc(1,sizeof(addfile_chain));
  3457.     if (*current) {
  3458.       (*current)->next=NULL;
  3459.       (*current)->pos=-1;
  3460.       (*current)->name[0]='\0';
  3461.     }
  3462.     if (*current) {
  3463.       strcpy((*current)->name,file);
  3464.       (*current)->pos=file_position;
  3465.       return 1;
  3466.     } else {
  3467.       printf("PANIC! Too many Java files during parsing [1]\n");
  3468.       return -1;
  3469.     }
  3470.   } else {                      /* copy last element in file and delete it */
  3471.     if (file)
  3472.       file[0]='\0';
  3473.     if (chain) {
  3474.       struct addfile_chain** current;
  3475.       int pos=-1;
  3476.       current=&chain;                     /* start from */
  3477.       while( (*current)->next ) {
  3478.         current=&( (*current)->next );    /* 'next' address */
  3479.       }
  3480.       if (file)
  3481.         strcpy(file,(*current)->name);
  3482.       pos=(*current)->pos;
  3483.       free(*current);
  3484.       *current=NULL;
  3485.       return pos;
  3486.     }
  3487.     return -1;                            /* no more elements */
  3488.   }
  3489.  
  3490.     /*
  3491.   static char* buffer;
  3492.   if (strlen(file)==8) {
  3493.     if (file[0]=='$') { // commande
  3494.       if (strcmp(file,"$BUFFER$")==0) {  // indiquer adresse buffer!
  3495.         buffer=file;    // le buffer
  3496.         buffer[0]='\0';
  3497.         return 1;
  3498.       }
  3499.     }
  3500.   }
  3501.   
  3502.   if (strlen(buffer)<32000) {   // vΘrifier..
  3503.     strcat(buffer,file);
  3504.     strcat(buffer,"&");  // sΘparateur
  3505.   } else {
  3506.     printf("PANIC! Too many Java files during parsing [1]\n");  // **
  3507.     buffer[32000]='\0';    // couper
  3508.   }
  3509.   */
  3510.  
  3511.   return 0;
  3512. }
  3513.  
  3514. #if HTS_ANALYSTE==2
  3515. // en train de parser un fichier html? rΘponse: % effectuΘs
  3516. // flag>0 : refresh demandΘ
  3517. int hts_is_parsing(int flag) {
  3518.   if (_hts_in_html_parsing) {  // parsing?
  3519.     if (flag>=0) _hts_in_html_poll=1;  // faudrait un tit refresh
  3520.     return max(_hts_in_html_done,1); // % effectuΘs
  3521.   } else {
  3522.     return 0;                 // non
  3523.   }
  3524. }
  3525. int hts_is_testing() {            // 0 non 1 test 2 purge
  3526.   if (_hts_in_html_parsing==2)
  3527.     return 1;
  3528.   else if (_hts_in_html_parsing==3)
  3529.     return 2;
  3530.   return 0;
  3531. }
  3532. // message d'erreur?
  3533. char* hts_errmsg() {
  3534.   return _hts_errmsg;
  3535. }
  3536. // mode pause transfer
  3537. int hts_setpause(int p) {
  3538.   if (p>=0) _hts_setpause=p;
  3539.   return _hts_setpause;
  3540. }
  3541. // rΘgler en cours de route les paramΦtres rΘglables..
  3542. // -1 : erreur
  3543. int hts_setopt(httrackp* opt) {
  3544.   if (opt) _hts_setopt=opt;
  3545.   return 0;
  3546. }
  3547. // ajout d'URL
  3548. // -1 : erreur
  3549. int hts_addurl(char** url) {
  3550.   if (url) _hts_addurl=url;
  3551.   return (_hts_addurl!=NULL);
  3552. }
  3553. int hts_resetaddurl() {
  3554.   _hts_addurl=NULL;
  3555.   return (_hts_addurl!=NULL);
  3556. }
  3557. // copier nouveaux paramΦtres si besoin
  3558. int copy_htsopt(httrackp* from,httrackp* to) {
  3559.   if (from->maxsite > -1) 
  3560.     to->maxsite = from->maxsite;
  3561.   
  3562.   if (from->maxfile_nonhtml > -1) 
  3563.     to->maxfile_nonhtml = from->maxfile_nonhtml;
  3564.   
  3565.   if (from->maxfile_html > -1) 
  3566.     to->maxfile_html = from->maxfile_html;
  3567.   
  3568.   if (from->maxsoc > 0) 
  3569.     to->maxsoc = from->maxsoc;
  3570.   
  3571.   if (from->nearlink > -1) 
  3572.     to->nearlink = from->nearlink;
  3573.   
  3574.   if (from->timeout > -1) 
  3575.     to->timeout = from->timeout;
  3576.   
  3577.   if (from->rateout > -1)
  3578.     to->rateout = from->rateout;
  3579.   
  3580.   if (from->maxtime > -1) 
  3581.     to->maxtime = from->maxtime;
  3582.   
  3583.   if (from->maxrate > -1)
  3584.     to->maxrate = from->maxrate;
  3585.   
  3586.   if (strnotempty(from->user_agent)) 
  3587.     strcpy(to->user_agent , from->user_agent);
  3588.   
  3589.   if (from->retry > -1) 
  3590.     to->retry = from->retry;
  3591.   
  3592.   if (from->hostcontrol > -1) 
  3593.     to->hostcontrol = from->hostcontrol;
  3594.   
  3595.   if (from->errpage > -1) 
  3596.     to->errpage = from->errpage;
  3597.  
  3598.   if (from->parseall > -1) 
  3599.     to->parseall = from->parseall;
  3600.  
  3601.  
  3602.   // test all: bit 8 de travel
  3603.   if (from->travel > -1)  {
  3604.     if (from->travel & 256)
  3605.       to->travel|=256;
  3606.     else
  3607.       to->travel&=255;
  3608.   }
  3609.  
  3610.  
  3611.   return 0;
  3612. }
  3613.  
  3614. #endif
  3615. //
  3616.  
  3617. // message copyright interne
  3618. void voidf(void) {
  3619.   char* a;
  3620.   a=""CRLF""CRLF;
  3621.   a="+-----------------------------------------------+"CRLF;
  3622.   a="|HyperTextTRACKer, Offline Browser Utility      |"CRLF;
  3623.   a="|                      HTTrack Website Copier   |"CRLF;
  3624.   a="|Code:         Windows Interface Xavier Roche   |"CRLF;
  3625.   a="|                    HTS/HTTrack Xavier Roche   |"CRLF;
  3626.   a="|                .class Parser Yann Philippot   |"CRLF;
  3627.   a="|                                               |"CRLF;
  3628.   a="|Tested on:                 Windows95,98,NT,2K  |"CRLF;
  3629.   a="|                           Linux PC            |"CRLF;
  3630.   a="|                           Sun-Solaris 5.6     |"CRLF;
  3631.   a="|                           AIX 4               |"CRLF;
  3632.   a="|                                               |"CRLF;
  3633.   a="|Copyright (C) Xavier Roche and others          |"CRLF;
  3634.   a="|Brought to you by Serianet, Caen, France       |"CRLF;
  3635.   a="|                                               |"CRLF;
  3636.   a="|Use this program at your own risks!            |"CRLF;    
  3637.   a="+-----------------------------------------------+"CRLF;
  3638.   a=""CRLF;
  3639. }
  3640.  
  3641.  
  3642. // HTTrack Website Copier Copyright (C) Xavier Roche and other contributors
  3643. //
  3644.  
  3645.